News & UpdatesProgrammingWeb programming StoreMy Projects
Links
Affiliates

Java Tutorial – 21 – Exception Handling

Exception handling allows programmers to deal with unexpected situations that may occur in their programs. As an example, the FileReader class in the java.io package is used to open a file. Creating an instance of this class will cause Netbeans to give a reminder that the class’s constructor may throw a FileNotFoundException. Attempting to run the program will also cause the compiler to point this out.

import java.io.*;
// …
FileReader in = new FileReader("Missing.file"); // error

Try-catch

To get rid of this compile-time error the exception must be caught by using a try-catch statement. This statement consists of a try block containing the code that may cause the exceptions, and one or more catch clauses. If the try block executes successfully the program will continue running after the try-catch statement, but if an exception occurs, execution will then be passed to the first catch block able to handle that exception type.

import java.io.*;
// …
try { 
  FileReader in = new FileReader("Missing.file"); 
}
catch(FileNotFoundException e) {}

Catch block

In the example above, the catch block is only set to handle the FileNotFoundException. If the code in the try block could throw more kinds of exceptions, and all of them should be handled in the same way, a more general exception can be caught instead, such as the Exception class itself. This catch clause would then be able to handle all the exceptions that inherit from this class, including the FileNotFoundException. Bear in mind that a more general exception needs to be caught after a more specific exception. The catch clause must always define an exception object. This object can be used to obtain more information about the exception, such as a description of the exception by using the getMessage method.

catch(FileNotFoundException e) {
  System.out.print(e.getMessage());   
}
catch(Exception e) {
  System.out.print(e.getMessage());   
}

Finally block

As the last clause in a try-catch statement, a finally block can be added. This block is used to clean up resources allocated in the try block and will always execute whether or not there is an exception. In this example, the file opened in the try block should be closed, but only if it was successfully opened. To be able to access the FileReader object from the finally clause it must be declared outside of the try block. Additionally, because the close method can also throw an exception it needs to be surrounded with another try-catch block. Keep in mind that if you forget to close a file Java’s garbage collector will eventually do it for you, but it is a good programming practice to do it yourself.

import java.io.*;
// …
FileReader in = null;
try { 
  in = new FileReader("Missing.file"); 
}
catch(FileNotFoundException e) { 
  System.out.print(e.getMessage()); 
}
finally { 
  if (in != null) {
    try { in.close(); } 
    catch(IOException e) {}
  }
}

Throwing exceptions

When a situation occurs that a method cannot recover from, it can generate its own exception to signal to the caller that the method has failed. This is done by using the throw keyword followed by a new instance of a Throwable type.

static void MakeException() throws Throwable
{
  throw new Throwable("My Throwable");
}

Checked and unchecked exceptions

Exceptions in Java are grouped into two categories – checked and unchecked – depending on whether or not they need to be specified. A method that throws a checked exception, for example IOException, will not compile unless it is specified by using a throws clause after the method’s parameter list and the calling method catches the exception. Unchecked exceptions on the other hand, such as the ArithmeticException, do not have to be caught or specified. Note that to specify multiple exceptions the exception types are separated by a comma.

import java.io.*;
// …
static void MakeException() throws IOException, 
                                   ArithmeticException
{
  throw new IOException("My IO exception");
  // …
  throw new ArithmeticException("Division by zero");
}

Exception hierarchy

Exceptions, like most everything else in Java, are classes that exist in a hierarchy. At the root of this hierarchy (below Object) is the Throwable class, and all descendants of this class can be both thrown and caught. Inheriting from Throwable there are the Error and Exception classes. Classes descending from Error are used to indicate non-recoverable exceptions, such as the OutOfMemoryError. These are unchecked because once they have occurred it is unlikely that the programmer can do anything about them even if they are caught.

Descending from Exception are the RuntimeExceptions, which are also unchecked. These are exceptions that can occur in almost any code, and it would therefore be cumbersome to catch and specify them. For example, a division by zero will throw an ArithmeticException, however surrounding every division operation with a try-catch would be bothersome. There is also an overhead associated with checking for exceptions and the cost of checking for these exceptions outweighs the benefit of catching them. The other Exception descendants, those that do not inherit from RuntimeExceptions, are all checked. These are exceptions that can be recovered from and that must be both caught and specified.

Recommended additional reading:
Sams - Teach Yourself Java in 24 Hours