The best programs are written so that computing machines can perform them quickly and so that human beings can understand them clearly. A programmer is ideally an essayist who works with traditional aesthetic and literary forms as
well as mathematical concepts, to communicate the way that an algorithm works and to convince a reader that the results will be correct. Donald E. Knuth

Exception Handling

Exceptions are unusual conditions or problems that arises during the execution of a program like divide by zero, running out of memory or accessing an array out of its bounds. Exception Handling is a mechanism to handle such conditions at run time and prevent abnormal termination or crashing of the program.

Types of Exception
There are mainly two categories of exceptions :
Checked Exceptions are typically the user errors which are ckecked at compile-time. For e.g IOException which might occur if we are trying to open a file that doesn't exist. SQLException is another type of checked exception.
Runtime Exceptions are checked at run-time and they occur due to some invalid input parameters, illegal memory access, etc. In the rest of this module, we will focus on run-time exception.

Throwing and Catching Exceptions
Whenever an erroneous situation occurs, the Java interpreter creates an object of Exception class and throws it. We can catch the exception object, display appropriate error message and take corrective action so that program continues to execute the remaining code without crashing. If the thrown object is not caught, the interpreter will display an error message and the program will terminate. The part of the code which is protected by exception handling is enclosed within try ... catch block. Following program illustrates the use of try and catch keywords :

class Division {
   int divide(int num, int denom) {
      try {
         int result = num / denom;
         return result;
      } catch(ArithmeticException ae) {
         System.out.println("Caught an exception : " + ae);
         return -9999; // return a garbage value to indicate error
      }
   }
}

public class TryCatchDemo {
   public static void main(String args[]) {
      Division dv = new Division();
      int res = dv.divide(17, 0);
      if ( res != -9999 ) {
         System.out.println("Result : " + res);
      }
   }
}

In the above program, if we pass the denominator as 0, an object of ArithmeticException class is thrown implicitly. This class is a subclass of Exception class. Now, let's see how to explicitly throw an exception using throw keyword. Throw keyword is mainly used to throw custom exception. We will see this later. Following program demonstrates the use of throw keyword :

public class ThrowDemo {

   /* this method validates if an integer is positive or not */
   static void validatePos(int num) {
      try {
         if (num < 0) {
            // negative integer, throw an exception
            throw new Exception("Negative integer");
         }
         else {
            System.out.println("Positive Integer : Number Validated");
         }
      } catch(Exception e) {
         System.out.println("Exception caught : " + e);
      }
   }

   public static void main(String args[]) {
      int value = -89;
      validatePos(value);
   }
}


Multiple catch blocks
A block of code can throw different types of exception during runtime. So, we need multiple catch blocks to handle different exception objects. Following program illustrates this concept :

public class MultipleCatchDemo {

   static void func() {
      try {
         int arr[] = { 7, 8, 9 };
         arr[9] = 56; // trying to assign a value to an invalid array index
      } catch(ArithmeticException e) {
         System.out.println("Arithmetic Exception : " + e);
      } catch(ArrayIndexOutOfBoundsException e) {
         System.out.println("Invalid Array Index Exception : " + e);
      } catch(NullPointerException e) {
         System.out.println("Null Pointer Exception : " + e);
      } catch(Exception e) {
         System.out.println("Unknown Exception : " + e);
      }
   }

   public static void main(String args[]) {
      func();
   }
}


finally block
The finally block consists of a piece of code that follows try ... catch block. This block is created using finally keyword and is always executed irrespective of whether or exception has occurred or not. It is mainly used to do some housekeeping activities like closing a file or stream.
Following program illustrates the use of finally keyword :

public class FinallyDemo {

   static void func() {
      try {
         int val = 17/0;
      } catch(ArithmeticException e) {
         System.out.println("Arithmetic Exception : " + e);
      } finally {
         System.out.println("Finally block executed");
      }
   }

   public static void main(String args[]) {
      func();
   }
}

In the above program, divide by 0 exception occurs which is caught and the finally block is executed. Even if there is no exception, still the finally block will be executed.

Defining Custom Exception
All the standard exceptions that we have seen so far ( ArithmeticException, NullPointerException, etc ) are subclasses of Exception class. Similarly, we can define custom exceptions by extending the Exception class. Following program demonstrates how to define and use custom exceptions :

/* define a custom exception class */
class IllegalValueException extends Exception {
   private int value;
   IllegalValueException(String str, int x) {
      super(str);
      value = x;
   }
   public int getValue() {
      return value;
   }
}

public class CustomExceptionDemo {

   /* this method validates if an integer is positive or not */
   static void validatePos(int num) {
      try {
         if (num < 0) {
            // negative integer, throw the custom exception
            throw new IllegalValueException("Negative integer", num);
         }
         else {
            System.out.println("Positive Integer : Number Validated");
         }
      } catch(IllegalValueException e) {
         System.out.println(e + " of value " + e.getValue());
      }
   }

   public static void main(String args[]) {
      validatePos(-889); // validate if a no. is positive or not
   }
}


throws keyword
If a method doesn't handle an exception, then it must declare it using throws keyword. This gives an indication that the method can thrown some exception during execution and it must be handled somewhere in the code flow. We will illustrate the use of throws keyword in the program show in next section on exception propagation.

Stack Unwinding ( Exception propagation )
An exception need not be caught in the method where it occurs. It can propagate through the call stack to reach the method which handles the raised exception. This process is also known as stack unwinding as all the entries regarding intermediate method calls are removed during the propagation process. Following program illustrates the mechanism :

public class ExceptionPropagationDemo {

   static void func1() throws Exception {
      throw new Exception("Demostrate exception propagation");
   }

   static void func2() throws Exception {
      func1();
   }

   public static void main(String args[]) {
      try {
         func2();
      } catch(Exception e) {
         System.out.println("Exception Caught : " + e);
      }
   }
}

In the above program, main( ) calls func2( ) which in turn calls func1( ). An exception is thrown in func1( ) but not handled there, so the exception propagates to func2( ) but it is not caught there also. Thus, it propagates to the bottom of the call stack i.e to the main( ) where it is handled. Please note the use of throws keyword int the method signature which indicates that the method is not catching any exception.

Re-throwing an Exception
After catching an exception, it can be re-thrown so that another method in the call stack handles it. Following program illustrates this behaviour :

public class RethrowException {

   static void func1() throws Exception {
      System.out.println("Throwing Exception from func1()");
      throw new Exception("Demostrate exception re-throw");
   }

   static void func2() throws Exception {
      try {
         func1();
      } catch(Exception e) {
         System.out.println("Re-throwing Exception caught in func2()");
         throw e;
      }
   }

   public static void main(String args[]) {
      try {
         func2();
      } catch(Exception e) {
         System.out.println("Re-thrown Exception caught in main()");
         e.printStackTrace(); // print the stack trace
      }
   }
}

In the above program, func2( ) catches the exception thrown in func1( ) and then re-throws that exception which is caught in main( ) method.

Common Java Exceptions
Following table shows some the common exceptions that are encountered :

ExceptionDescription
ArithmeticExceptionMathematical errors like divide by 0.
ArrayIndexOutOfBoundsExceptionAccessing non-existent array index.
IOExceptionI/0 failures like unable to read from input device or file.
FileNotFoundExceptionAccessing non-existent files.
NumberFormatExceptionConversion from string to integer fails.
NullPointerExceptionReferencing a NULL object.
OutOfMemoryExceptionNot enough memory available to allocate a new object.

Back | Next