how2examples.com
Home - Introduction to Java Programming

Java Exception Handling

Java provides a mechanism for handling exceptional conditions that occur during the execution of a program. Java's exception handling allows developers to seperate exception generation from exception handling. The exception is "thrown" by a program when an exceptional event occurs. The part of the code that "catches" the thrown exception is called an "exception handler".

Throwing Exceptions

The two steps for throwing an exception are:

Normally these two steps are combined in to a single statement:

throw new IllegalStateException("description of the exception");

Catching Exceptions

To deal with an exception you can enclose the code that may throw the exception inside a try block followed by a catch block that contains code for handling the exception.

try {
   throw new IllegalStateException("description of the exception");
} catch (IllegalStateException e) {
}

Catching Multiple Exceptions

A try block can have more than one corresponding catch block. A try block can have a catch block for a particular subclass of exception and another catch block for its parent class. The catch block for more specific exceptions must precede more general ones (e.g. if both are present, the catch block for java.io.FileNotException must be before the catch block for java.io.IOException). Only one catch block, the first applicable one, will be executed.

Propagating Exceptions

If a method does not catch exceptions that can be generated by the code it contains then the exception is "propagated" upwards to the method that called it.

Contents of PropagatingExceptionsExample.java:
public class PropagatingExceptionsExample {
   public static void main(String[] args) {
      x();
   }

   static void x() {
      try {
         y();
      } catch (IllegalStateException e) {
         System.out.println("IllegalStateException in x():  " + e.getMessage());
      } catch (Exception e) {
         System.out.println("Exception in x(): " + e.getMessage());
      }
   }

   static void y() {
      try {
         System.out.println("Before call to z()");
         z();
         System.out.println("After call to z()");
      } catch (NullPointerException e) {
         System.out.println("NullPointerException in y(): " + e.getMessage());
      }
   }

   static void z() {
      throw new IllegalStateException("Exception generated by z() method");
   }
}
Command to compile PropagatingExceptionsExample.java:
javac PropagatingExceptionsExample.java
Command to run PropagatingExceptionsExample:
java PropagatingExceptionsExample
Output from running PropagatingExceptionsExample:
Before call to z()
IllegalStateException in x():  Exception generated by z() method

Exception Hierarchy

There are three fundamental and distinct subsets of java.lang.Throwable.

A subset of the Java exception hierarchy
A subset of the Java exception hierarchy
(Click image to see larger version.)

As checked exceptions are expected to be dealt with there are specific rules on their use, enforced at compile-time, that are only optional for errors and runtime exceptions. A method that contains statements that may throw a checked exception must either:

An overriding method may not throw a checked exception unless the overridden method also throws that exception.

Contents of OverridenThrowsExample.java:
import java.io.FileNotFoundException;
import java.io.IOException;

public class OverridenThrowsExample {
   public static void main(String[] args) {
      try {
         new B().x();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

class A {
   void x() throws FileNotFoundException {
   }
}

class B extends A {
   void x() throws IOException {
   }
}
Command to compile OverridenThrowsExample.java:
javac OverridenThrowsExample.java
Result of trying to compile OverridenThrowsExample.java:
OverridenThrowsExample.java:20: x() in B cannot override x() in A; overridden method does not throw java.io.IOException
   void x() throws IOException {
        ^
1 error

Finally Block

The try block can optionally have a finally block. The finally block must be after the try block and all of the associated catch blocks. The contents of the finally block will be executed after the body of the try block even if an exception was thrown.

Contents of FinallyExample.java:
public class FinallyExample {
   public static void main(String[] args) {
      try {
         throw new RuntimeException();
      } catch (Exception e) {
         System.out.println("Caught exception");
      } finally {
         System.out.println("Finally block A");
      }
   
      try {
         // do nothing
      } catch (Exception e) {
         System.out.println("Caught exception");
      } finally {
         System.out.println("Finally block B");
      }
      
      try {
         throw new RuntimeException();
      } finally {
         System.out.println("Finally block C");
      }
   }
}
Command to compile FinallyExample.java:
javac FinallyExample.java
Command to run FinallyExample:
java FinallyExample
Output from running FinallyExample:
Caught exception
Finally block A
Finally block B
Finally block C
Exception in thread "main" java.lang.RuntimeException
   at FinallyExample.main(FinallyExample.java:20)

See Also