Java Exception Hierarchy

In the previous chapter, we have seen that an InputMismatchException can be caught by a catch block defined to handle an exception of type ‘Exception’ since InputMismatchException is a subclass of Exception. It is important to know the hierarchy of exception classes to write correct programs.

Class Exception lies at the root of the exception hierarchy. Every exception type in Java is a subclass of Exception. Therefore, a catch clause designed to handle Exception can process all pre-defined exceptions in Java. However, besides the subclasses of Exception, we have subclasses of Error, which represents a condition the programmer cannot handle.

The exceptions that inherit from Error denote serious errors like VirtualMachineError from which a program cannot normally recover. Though it is syntaxialy correct to catch Errors also, one however should refrain from doing so. Both Exception and Error are subclasses of Throwable. (We have both the Throwable class and the Throwable interface).

We have extended several other Exceptions from the class Exception. We can group them into two categories. We can add the Runtime Exception to one category and all other exceptions in the other category. We will see shortly why we have grouped them in this way. The following diagram shows this hierarchy.

exception hierarchy in java

Java distinguishes between checked and unchecked exceptions. Checked exceptions are those Exceptions for which we need to provide exception handling, while unchecked exceptions are those for which providing exception handlers are optional. You may know the exceptions that would be thrown by looking at the documentation for the method that you are calling.

For example, when we are calling the nextInt() method to take an integer input from the keyboard, we should also know the exceptions that it might throw. Look at the documentation for this method.

You see that three types of Exceptions may be thrown by this method. Even though we have not provided exception handlers for these three methods, the compiler has raised no objection. This is because these three Exceptions are unchecked exceptions. All exceptions of type RunTimeExcepotion or its subclasses are considered unchecked Exceptions.

Also, all exceptions of type Exception other than RunTimeExcepotion have checked exceptions. Checked exceptions should either be caught or declared to be thrown. We shall see shortly how we may throw exceptions instead of catching them.

Here are a few Exceptions that you should be familiar with:

ArrayIndexOutOfBoundsException (unchecked): Thrown when we try to access an array element using an invalid index, such as a negative index or an index greater to or equal to the length of the array StringIndexOutOfBoundsException (unchecked): Similar to the above but deals with Strings enacted of arrays IndexOutOfBoundsException (unchecked): A superclass of the above two Exception types NullPointerException (unchecked): Thrown when we try to dereference a null pointer i.e. when we try to access an object through a variable when the variable holds a value of null and does not hold a reference to an object

We need to keep the hierarchy of exceptions in mind when writing exception handlers for our program. For example, let us provide two catch blocks for the program we have written earlier, which takes an integral and displays it. One of these catch statements will be catching the InputMismatchException and we will define the other to catch a general Exception. Now, what would happen if we defined the catch block for Exception first, followed by a catch block for InputMismatchException?

catch (Exception e ) {
    // code
catch (  InputMismatchException e ) {
    // code

Now, compile this program. You will receive an unreachable code error saying that the program can never reach the second catch handler. Why does this happen? Assume that the program compiles well and we can execute it. If we enter a valid number, we will execute a no catch statement. If we enter an invalid input like a String, an InputMismatchException will be thrown.

As already said, we will compare the type of Exception thrown with the types specified in the catch clauses in sequential order. So, we would compare the type InputMismatchException with the type Exception. Since InputMismatchException is a subclass of Exception, a match has occurred. The first catch block will be executed.

Once a catch block is executed, the remaining blocks will be skipped and control will pass onto the final block if they exist. So, in conclusion, the second catch block would never be executed. Therefore, an unreachable code compilation error was generated. Therefore, we needed to catch subclass exceptions before catching superclass exceptions. The proper way to define the above code is to capture InputMismatchException first, followed by Exception as shown below.

catch (  InputMismatchException e ) {
    // code
catch (Exception e ) {
    // code

Leave a Reply

4 + four =