Checked and Unchecked Exceptions in Java

Exception handling in java lets you create robust applications in Java. A lot of people gets confused over what are checked and unchecked exceptions. Exceptions are also distinguished into JVM exceptions and programmatic exceptions. Let’s decipher these terms.

Checked Exceptions

Checked exceptions are exceptions which you must handle properly in your code. The compiler will force you to properly handle these exceptions. You can either catch these exceptions or declare them in the throws clause of your method.

Generally checked exceptions occur due to conditions beyond your control, like IOException if a network connection fails. But your application should anticipate such conditions and handle them properly so that your application doesn’t crash. This is why you are forced by the compiler to handle these exceptions. Like if the network connection is broken during a file transfer, your application should handle it and allow the user to try again.

Unchecked Exceptions

Unchecked exceptions, on the other hand, occur due to coding errors on the part of the programmer. Like a NullPointerException can be avoided by checking if a reference is null.

There are also some unchecked exceptions which can occur without much fault of the programmer. These are exceptions which are subclasses of java.lang.Error class. When these exceptions occur, there isn’t much that you can do, so you are not forced to handle them as you can’t anticipate when they’ll occur. Like an OutOfMemoryError can occur anytime an object is instantiated, so you can’t wrap each object instantiation in try catch blocks.

Learn By Example

Lets create a toy program to see how compiler forces us to handle Checked exceptions. The following program will fail to compile because we are not handling the checked exception,

class UnhandledException {
    public static void main(String[] args) {
        throw new Exception();
    }
}

To make the above code compile, we can either wrap the throw statement in a try catch block or declare Exception in the throws clause of main method. If main method threw an unchecked exception, then the compiler would not complain about it not being handled. So the following code will compile without any problems,

class UnhandledException {
    public static void main(String[] args) {
        throw new NullPointerException();
    }
}

Exception class hierarchy

The exception class java.langThrowable is a checked exception. The Java API defines two subclasses of Throwable. These are java.lang.Exception and java.lang.Error. Error is unchecked exception class while Exception is checked exception class. Exception class itself has an unchecked sub-class java.lang.RuntimeException. The unchecked exceptions like NullPointerException, ClassCastException etc are all sub-classes of RuntimeException. All subclasses of RuntimeException and Error are unchecked exceptions. Other exceptions are all checked exceptions.

Checked and Unchecked Exceptions in Java

If you create your own exception class, then whether your exception is checked or unchecked depends which Exception class it sub-classes. If your exception class extends a checked exception class, then your exception class will also be a checked exception. And if your exception class extends an unchecked exception class, then your exception class will also be an unchecked exception.

There is a rule with checked exceptions which sometimes confuses people. If in your catch block you are catching a checked exception, then there must be a possibility of its occurrence in the associated try block.. So the following code will fail to compile,

try {
    System.out.println("...");
} catch(java.io.IOException ioe) {
}

The compiler will report that IOException is never thrown in the try block, so you can’t catch it. This rule doesn’t apply to unchecked exceptions, if you are catching an unchecked exception which is not thrown in the try block, the compiler is fine with it. This gets a little confusing with Exception and Throwable classes. Both are checked exception classes, but you can catch them without any exception being thrown in the associated try block. So this code will compile fine,

try {
    System.out.println("...");
} catch(Exception ex) {
}

The rules are different for Throwable and Exception and other checked exception classes. This is because both Exception and Throwable have unchecked exceptions as subclasses. So the compiler allows you to catch them thinking that you might be trying to catch an unchecked exception. Remember the compiler is not concerned with unchecked exceptions. RuntimeException is a subclass of Exception and Error is a subclass of Throwable, and both RuntimeException and Error are unchecked exception classes. So when I write this code,

try {
    System.out.println("...");
} catch(Exception ex) {
}

The compiler allows this because Exception can also catch unchecked exceptions (RuntimeException and its subclasses). Similarly the following code is allowed because Throwable can catch unchecked exceptions (RuntimeException and Error and their subclasses),

try {
    System.out.println("...");
} catch(Throwable ex) {
}

JVM and programmatic exceptions

Now we are on to the last topic in this tutorial. Understanding the difference between JVM and programmatic exceptions will help you understand the exception handling mechanism a little better.

JVM exceptions are thrown by the JVM itself. Like if I call a method on a null reference, then the JVM will throw a NullPointerExceptions. Or if you divide 10 by 0, you’ll get an ArithmeticException. These exceptions are automatically thrown by the JVM. There is a limited set of JVM exceptions.

All other exceptions are programmatic exceptions. Somewhere or the other they are thrown using the throw clauseThey are explicitly thrown in the code using throw clause. Lets take the example of NumberFormatException. NumberFormatException is thrown by methods like Integer.parseInt or Float.parseFloat. It is a programmatic exception. In the source code of Integer class, you can find statement like this in the parseInt method,

if (s == null) {
      throw new NumberFormatException("null");
}

So basically the JVM never throws these types of exceptions on its own. They are explicitly thrown in the code using throw clause. You can also throw JVM exceptions using the throw clause like I can write a code which is like this,

if (s == null) {
      throw new NullPointerException("I told you s shouldn't be null");
}

But generally JVM exceptions are not thrown by us. All of the JVM exceptions are unchecked. Programmatic exceptions can be checked or unchecked.

This concludes this tutorial on exceptions handling. Please use the comments form below if you have any queries or comments related to this tutorial.