Return to Course Content Home

Exceptions

Optional Reading

Read the Java Tutorial on Exceptions.

What is an Exception

By definition, an exception is an event that occurs that was not planned, and it disrupts the normal flow of a program. You can think of exceptions as a type of error condition that occurs, and the Exception mechanism allows you to "gracefully" handle the error, instead of crashing the program. When an Exception occurs, the event contains quite a bit of useful information, that can be used to either handle the event, or at least document what went wrong.

The Exception event contains a message describing the event, a complete stack trace of where the event occured and some other information.

When you (or the system) creates an Exception event, it is referred to as "throwing an Exception". This terminology ties in with the coding style that defines an Exception and its error handling capabilities.

Now, it is reasonable to ask, "Why have exceptions? Can't we just run tests and code around the different conditions?" Actually, you can, but the use of Exceptions makes for cleaner, more organized code, and it separates the error handling code into specific regions, keeping normal program flow separate from error conditions.

Another feature of Exceptions is the propagation of the event up the Call Stack to an arbitrary handler in the same or a calling Object. When we look at how definitions are defined, you can see they are handled two ways. The first is an "immediate" handling of the event in the method generating the error, but the second is that the surrounding event can just declare that it doesn't actually handle the event, but the Object calling the method must handle it. It turns out this is *very* powerful and flexible, and it can keep your code much more organized.

An additional advantage is that Exceptions are handled, and grouped by Class, which allows for organization of behavior within your error handling code.

As an example, there is an existing Java class called Integer. Go to the documentation you downloaded on Java and look at class Integer. In the bottom right window, find the Integer class and select it. If you scroll down, you will see something that looks like this:

java.lang.Integer
Exception

click on the parseInt link in your browser, which will take you to the method documentation.

java.lang.Integer
Expetion

Note that the method throws a NumberFormatException. Let's think about what this method does.

If you pass it a string of "5", it will convert the string into the integer 5. Fairly simple, right? But think about what happens if you pass it the string "Hello"....

If you didn't use exceptions, how would you test for failure, what value could you return from the method to indicate there was an unexpected condition?

In C++, you could pass a pointer to a value in the arguments that would store the actual result of the method, and then just use the return value from the method as a measure of success. You could even fake this in Java by passing an Object in the argument, and then setting it's attribute.

It turns out, it is much cleaner to just return the correct value, but if something unexpected comes up, you throw the exception. Since this is a Runtime exception, it doesn't even have to be caught in the code, but it is good practice to do so.

The other case is when a method may return return more than one type of error. The java.io.BufferedReader class has a skip(long n) method that returns two types of Exceptions:

java.io.BufferedReader
Two Exceptions

One final aspect of Exceptions that isn't mentioned that often is that there are times when the object you are coding really has no business trying to handle the error itself. Instead, it needs to signal classes that use it that they should account for certain error conditions. By using exceptions, you can require objects that use your methods to account for some anticipated problems when running your class.

Best Practice

Even though you may be tempted, you don't really want to catch the Exception superclass.

try {
  Integer.parseInt(foo);
} catch (Exception e) {
// do something here
}

The problem here is that you really should catch the Exception you *think* will happen, which is a NumberFormatException. If you catch any and all Exceptions, you might hide a truly unexpected situation (like foo is null instead of bad text) and never even realize it. It may not happen every time, but sooner or later, catching the "Exception" class instead of it's subclass will get you in trouble by hiding an Exception type you never thought you'd get.

So, what you want to use, assuming you are trying to parse some text a user typed in is:

try {   Integer.parseInt(foo);
   } catch (NumberFormatException nfe) {
 // do something here
 }

Practice

Download the Eclipse project exceptions.zip.

Take a look at the code and how the exceptions are handled. Post any comments/questions to the Discussion forum.

Summary

Proper use of exception-handling produces much more stable and robust code. Java's exception handling provides the following benefits:

  1. It separates your main code from error handling code. The use of the try-catch clauses explicitly places the error handling code in a certain area within your source code.
  2. It allows you to merely signal an error by throwing an exception and letting the code that calls yours handle the exception. Many times, error handling code is not appropriate in a class and the calling classes should know how to handle the exception.
  3. The use of the compiler to ensure that certain declared exceptions are handled ensures that these situations are anticipated.