by David Wood

This week we're going to fill in some more detail regarding exceptions in Java.

Last week we showed you a simple example about the use of exceptions by way of talking about the use of a Java applet's parameters.


int displaySpeed = 0;

  ... 

String displaySpeedString = getParameter("DISPLAYSPEED");

   if (displaySpeedString != null) {

      try {

          displaySpeed = Integer.parseInt(displaySpeedString);

      } catch (NumberFormatException e) {

          displaySpeed = // SOME DEFAULT VALUE.

      }

   }

(This is adapted from the example on the Sun Java Tutorial page on parameters.)

To be more specific, and employ some of the dreaded exception-handling jargon, the above block of code represents an exception handler. In order to clarify what the experts mean by this figure of speach, we have to clarify more exactly how exceptions work inside of the language.

Think of an exception itself as an object, not an event. In Java, exceptions are all subclassed from a specific kind of object, called Throwable. Directly subclassed from this, there is a generic Exception class from which all the more specific exceptions you might deal with as a programmer are derived; specifically, in this case, from which the NumberFormatException is derived.

The exception itself is frequently encapsulating only a few pieces of information (usually relevant to the reason the exception was thrown) as it is passed from the throwing routine to the catching routine. Something beginners with exceptions frequently confuse is the importance of the object itself versus the importance of the throw.

To throw an exception is to halt your execution, instantiate (create) an exception object, and then search for the appropriate exception handler. This is accomplished by doing something called (in a suitably arcane manner) propagating the exception up the call stack. Without going into too much detail, you can think of the call stack as the ordered list of methods that have been called since your program began its execution. In other words, in pseudocode:



applet {
   myFunction();
}

myFunction {
   subFunction();
}

subFunction {
   systemFunction();
}


applet will be placed on the call stack, followed by myFunction, and lastly subFunction, by virtue of the fact that they were called (used). If systemFunction throws an exception, the metaphor frequently used is that the exception object "bubbles" upward through the calling methods on the stack, "looking" in each for a catch segment within an exception handler that will catch the exception object's type. As above, when a NumberFormatException is thrown, it looks for a "catch NumberFormatException" statement. In this case, if there was no exception handler, our hypothetical exception would look in subFunction, myFunction, and applet, and then when the call stack was completely "emptied," the entire program would terminate.

There is something important that we're leaving out, however, and that's that the Java language enforces a special rule when exceptions come into play. In general, if your routines throw exceptions, or you use anyone else's routines (including the standard Java methods) that do, every calling method must either handle any exception that could potentially be thrown, or throw it further "upward." Attempting to use a method that throws an exception you do not "handle" in some fashion will cause an error when you attempt to compile. There's an exception to this rule, of course; there is a class of exceptions that do not need to be handled specifically, namely, "Runtime Exceptions."

Next week, we'll elaborate on this, discuss the exception hierarchy in greater detail, and give a few more specific examples.

Past installments of Java Jolt

http://www.internet.com/