Way2Java

Rules of Exceptions in Multiple Catch Blocks

Generally, it is a good programming practice to write one problematic statement (that may throw an exception) in one try block. If the same one statement is prone to multiple problems, then it is required to write multiple catch blocks or by chance if the try block contains multiple problematic statements (generally done in rough code development), then also multiple catch blocks required.

Programmer should be careful in writing multiple catch blocks. let us discuss all the pros and cons.

First observe this program.

public class Demo
{
  public static void main(String args[])
  {
    int a = 0, b[] = { 10, 20, 30 };   

    try
    {
      System.out.println(b[3]/a);
    }
    catch(ArithmeticException e)
    {
      System.out.println("Do no divide by zero sir.\n" + e);
    }
    catch(ArrayIndexOutOfBoundsException e)
    {
      System.out.println("Do not cross the size of the array sir.\n" + e);
    }
  }
}

Observe the following statement

      System.out.println(b[3]/a);

Assume that you are taking input from the user for both numerator and denominator. User can create two problems – entering an index value that is beyond the size of the array b or the divisor value a. Now as a programmer how you can solve the problem. One way is taking multiple catch blocks as in the above example. Now the order of catch blocks (which must come first and the other later) with the handlers of ArithmeticException and ArrayIndexOutOfBoundsException can be anyone as both exceptions are siblings of RuntimeException.

The problem comes if one is super class exception and the other one is subclass exception. Observe the following simple code that opens a file, read the contents and print at the command prompt.

import java.io.*;
public class Demo
{
  public static void main(String args[])
  {
    try
    {
      FileInputStream fis = new FileInputStream("author.txt");
      int k;
      while( ( k = fis.read() ) != -1)
      {
        System.out.print((char)k);
      }
      fis.close();
    }
    catch(FileNotFoundException e)
    {
      System.out.println("Source file does not exist.\n" + e);
    }
    catch(IOException e)
    {
      System.out.println("Some I/O problem.\n" + e);
    }
  }
}

The importance here is not the program and not the output; they are very trivial. The important is order of catch blocks. You know that FileNotFoundException is the subclass IOException. First the subclass exception block should come and later its super class IOException block. Of course, this is the way written in the above code. If the order is changed, the compiler does not compile the code. Observe the following code.

    catch(IOException e)
    {
      System.out.println("Some I/O problem.\n" + e);
    }
    catch(FileNotFoundException e)
    {
      System.out.println("Source file does not exist.\n" + e);
    }

In the above code first super class exception IOException is written. It is a compilation error. Compiler complains "FileNotFoundException has already been caught". See the above output screen.

What does it mean?

One provision in exceptions design is "superclass exception can handle (or catch) subclass exception" also; But at the cost of the performance. As per this provision, the IOException, being super class of FileNotFoundException, is capable to handle subclass exception FileNotFoundException also. So the execution control never comes to the catch block containing FileNotFoundException, of any number of executions. This is known as "unreachable code". Unreachable code is an error in Java language.

So it is a rule in Java, if multiple catch blocks exist, the first catch block should have subclass exception and the next catch block should have its super class exception and the so on.

Would you like to know two more unreachable codes in Java that raise compilation error? Following are.

public int display()
{
  System.out.println("Hello 1");
  return 100;
  System.out.println("Hello 2");
}

The return statement is known as jump statement because the control jumps to the calling method and after executing the calling method, the execution control never returns to the calling method. This is an error. Following is the other one.

switch(1)
{
  case 1:
    System.out.println("Hello 1");
    break;
    System.out.println("Hello 2");
}

The break is also a jump statement and causes compilation error as the second println() never executes in its life.

1. For rules of exceptions in method overriding refer Rules of Exceptions in Method Overriding.
2. For rules of access specifiers in method overriding refer Rules of Access Specifiers in Method Overriding.