Handling ExceptionsJ8 Home « Handling Exceptions

Now we know what the Java exception hierarchy looks like and the classes involved its time to start handling exceptions which may occur within our code. Exception control in Java is achieved using the try, catch, finally, throw and throws keywords.

The throw keyword allows us to throw exceptions and we can declare exceptions from within our methods using the throws keyword. Both these keywords are discussed in much greater detail in the next lesson Declaring Exceptions.

In this lesson we focus on the try, catch and finally keywords and how we use them to handle exceptions in our code. The try keyword is used with a code block to put the code that may cause an exception in. The catch keyword is used with a code block to put the code to handle an exception in. The finally keyword is used with a code block to put the code that must be run whether there is an exception or not.

try catch finally  Construct Top

The following table shows the different forms of the try catch finally construct.

Construct Description
try catch
try {
    // Code to be monitored for exception goes here
}
catch (Exception ex) {
    // Code to be executed on exception
}

Execute statements in try code block.


Execute statements in catch code block.
try catch finally
try {
    // Code to be monitored for exception goes here
}
catch (Exception ex) {
    // Code to be executed on exception
}
finally () {
    // Code to be run whether exception or not
}

Execute statements in try code block.


Execute statements in catch code block


Execute statements in finally code block.
try finally
try {
    // Code to be monitored for exception goes here
}
finally () {
    // Code to be run whether exception or not
}

Execute statements in try code block.


Execute statements in finally code block.
try with multiple catch
try {
    // Code to be monitored for exception goes here
}
catch (Exception1 ex1) {
    // Code to be executed on exception 1
}
catch (Exception2 ex2) {
    // Code to be executed on exception 2
}
...
catch (ExceptionN exN) {
    // Code to be executed on exception N
}

Execute statements in try code block.


Execute statements in catch code block 1.


Execute statements in catch code block 2.



Execute statements in catch code block N.
try with multiple catch and a finally
try {
    // Code to be monitored for exception goes here
}
catch (Exception1 ex1) {
    // Code to be executed on exception 1
}
catch (Exception2 ex2) {
    // Code to be executed on exception 2
}
...
catch (ExceptionN exN) {
    // Code to be executed on exception N
}
finally () {
    // Code to be run whether exception or not
}

Execute statements in try code block.


Execute statements in catch code block 1.


Execute statements in catch code block 2.



Execute statements in catch code block N.


Execute statements in finally code block.

try catch finally  Rules Top

When using the try catch finally construct there are certain rules that must be adhered to or you get a compiler error:

  • When using a try block it must be accompanied by a catch block, a finally block or both.
  • When using a catch block it must immediately follow the try block.
  • When using multiple catch blocks they must go in order from the most specific error to the most generic as discussed later in the lesson in Exceptions And Polymorphism.
  • When using a finally block it must immediately follow the last catch block, or the try block when no catch block is present.

Creating A Folder For Our Flow Control Source Files

As we are about to do the first code example of a new section lets create a folder for our Flow Control files, in Windows this would be:

double click My Computer icon

double click C:\ drive (or whatever your local drive is)

right click the mouse in the window

from the drop down menu Select New

click the Folder option and call the folder _FlowControl and press enter.

Using  try catch Top

The try catch construct is the most commonly used of the three forms of the try catch finally construct listed in the table above. To get us started we will write a class that will cause a runtime error by trying to divide by zero.


package info.java8;
/*
  A DivideByZero class
*/ 
public class DivideByZero {
    public static void main(String[] args) {
        int a = 5 / 0; // JVM will not like this
    }
}

Save, compile and run the DivideByZero class in directory   c:\_FlowControl in the usual way.

run divide by zero

The above screenshot shows the output of running our DivideByZero class. We got an ArithmeticException exception when we tried to divide by zero as expected.

This is not a very elegant termination of our program and will mean nothing to a general user of the software. It also means termination of the program so any code won't get executed. We will rework the code using a try catch to output a message instead.


package info.java8;
/*
  A DivideByZero class
*/ 
public class DivideByZero {
    public static void main(String[] args) {
        /*
          We put the code we think might cause a problem in a try block
        */ 
        try {
            int a = 5 / 0; // JVM will not like this
        }  
        /*
          We handle the exception in a catch block
        */ 
        catch (Exception ex) {
            System.out.println("We caught exception: " + ex);
        }  
        System.out.println("We can just continue on now.");
    }
}

Save, compile and run the DivideByZero class in directory   c:\_FlowControl in the usual way.

run divide by zero2

The above screenshot shows the output of running our reworked DivideByZero class. This time we catch the ArithmeticException exception and continue on with our code.

Using  try catch finally Top

We use the try catch finally construct when we want to action some code regardless of the outcome of an action that might cause an exception. Whatever we put into the finally code block is guaranteed to run whether an exception occurs or not. There are many reasons to include a finally statement, such as freeing resources and removing code duplication. In the following examples we will use a try catch and then remove code duplication by replacing it with a try catch finally version:


package info.java8;
/*
  A NumberFormatException class
*/ 
public class NFE {
    public static void main(String[] args) {
 
        System.out.println("We are turning on the timer.");
        try {
            System.out.println("Timer set for " + Integer.parseInt(args[0]) + " minute(s).");
            System.out.println("We are turning off the timer.");
        }  
        catch (Exception ex) {
            System.out.println("We caught exception: " + ex);
            System.out.println("We are turning off the timer."); // Code duplication
        }  
    }
}

Save, compile and run the NFE class in directory   c:\_FlowControl passing 1, then run again passing one.

run number format exception

The above screenshot shows the output of running our NFE class when we pass 1 andone. We got a NumberFormatException when we passed one. The point is that in this rather contrived class we always want to send a message that the timer is turned off and the only way to do that is to duplicate code. We will rework the class to use finally to get rid of the duplicated code:


package info.java8;
/*
  A NumberFormatException class
*/ 
public class NFE {
    public static void main(String[] args) {
 
        System.out.println("We are turning on the timer.");
        try {
            System.out.println("Timer set for " + Integer.parseInt(args[0]) + " minute(s).");
        }  
        catch (Exception ex) {
            System.out.println("We caught exception: " + ex);
        }  
        finally {
            System.out.println("Finally will always get executed whether an exception occurs or not.");
            System.out.println("We are turning off the timer.");
        }  
    }
}

Save, compile and rerun the reworked NFE class in directory   c:\_FlowControl passing 1, then run again passing one.

run number format exception2

The above screenshot shows the output of running our reworked NFE class when we pass 1 andone. We got a NumberFormatException when we passed one. As you can see the finally block always runs whether an exception occurs or not.

Using  try finally Top

We can also use the try finally construct and maybe a possible reason for using this would be for an application that does some processing and closes down after freeing the resouces. In this example we will use a try finally to print some simple messages:


package info.java8;
/*
  A DivideByZero2 class
*/ 
public class DivideByZero2 {
    public static void main(String[] args) {
 
        System.out.println("Starting application.");
        try {
            int a = 5 / 0; // JVM will not like this
        }  
        finally {
            System.out.println("Finally is always processed.");
            System.out.println("Closing application.");
        }  
    }
}

Save, compile and run the DivideByZero2 class in directory   c:\_FlowControl in the usual way.

run divide by zero 2

The above screenshot shows the output of running our DivideByZero2 class. We got a We got an ArithmeticException exception when we tried to divide by zero as expected. The finally block always runs and in our example we print some messages before the runtime exception crashes the application.

Exceptions And Polymorphism Top

In all the above code examples we have been using the Exception object as the parameter within our catch blocks. The Exception class is the superclass of all exceptions, as we saw when we looked at the Exception Hierarchy Diagram in the last lesson. We have been using the Exception class polymorphically to act like a catch all for any exception objects that are created and thrown from its subclasses. We can have finer grained control over what we do about an exception by using multiple catch blocks catering for the exceptions we need to handle. Lets look at part of the exception hierarchy from the last lesson and write some code to illustrate how we do this:

exception hierarchy

In the code below we have added some extra catch blocks to the NFE class we wrote earlier in the lesson:


package info.java8;
/*
  A NumberFormatException class
*/ 
public class NFE {
    public static void main(String[] args) {
 
        System.out.println("We are turning on the timer.");
        try {
            System.out.println("Timer set for " + Integer.parseInt(args[0]) + " minute(s).");
        }  
        catch (Exception ex) {
            System.out.println("We caught exception: " + ex);
        }  
        catch (NumberFormatException ex) {
            System.out.println("An invalid number was passed: " + ex);
        }  
        catch (ArrayIndexOutOfBoundsException ex) {
            System.out.println("An invalid argument was passed " + ex);
        }  
        finally {
            System.out.println("Finally will always get executed whether an exception occurs or not.");
            System.out.println("We are turning off the timer.");
        }  
    }
}

Save and compile and the reworked NFE class in directory   c:\_FlowControl.

run number format exception2

The above screenshot shows the output of compiling our reworked NFE class, we got a compiler error. The reason for the error is that we have the catch all Exception class in our first catch block, which will catch every exception. This means the other two exceptions can never be reached. When we code multiple catch blocks, we have to work up the inheritance tree from the most specific exception to the most generic. So in our code and using the exception hierarchy diagram above we can see that the catch blocks should be ordered NumberFormatException or ArrayIndexOutOfBoundsException which are the lowest in the inheritance tree. The order of these two doesn't matter as they are at the same level of the inheritance hierarchy. The catch all Exception comes after these two. In the code below we have put the catch blocks in the correct order.


package info.java8;
/*
  A NumberFormatException class
*/ 
public class NFE {
    public static void main(String[] args) {
 
        System.out.println("We are turning on the timer.");
        try {
            System.out.println("Timer set for " + Integer.parseInt(args[0]) + " minute(s).");
        }  
        catch (NumberFormatException ex) {
            System.out.println("An invalid number was passed: " + ex);
        }  
        catch (ArrayIndexOutOfBoundsException ex) {
            System.out.println("An invalid argument was passed " + ex);
        }  
        catch (Exception ex) {
            System.out.println("We caught exception: " + ex);
        }  
        finally {
            System.out.println("Finally will always get executed whether an exception occurs or not.");
            System.out.println("We are turning off the timer.");
        }  
    }
}

Save, compile and rerun the reworked NFE class in directory   c:\_FlowControl with no arguments, then run again passing 1, then run again passing one.

run number format multi catch

The above screenshot shows the output of running our reworked NFE class with no passed arguments, when we pass 1 and one. We got an ArrayIndexOutOfBoundsException when we didn't pass any arguments and output an error in the catch block for that exception. When we passed a 1 the code runs fine. When we pass one we got a NumberFormatException and output an error in the catch block for that exception. As you can see the finally block always runs whether an exception occurs or not.

Lesson 2 Complete

In this lesson we looked at handling exceptions which may occur within our code.

What's Next?

In the next lesson we learn how to use the throw keyword which allows to throw exceptions from within our methods. We also investigate how to declare exceptions using the throws keyword.