How to Throw Exceptions

Before you can catch an exception, some code somewhere must throw one. Any code can throw an exception: your code, code from a package written by someone else (such as the packages that come with the Java platform), or the Java runtime environment. Regardless of what throws the exception, it's always thrown with the throw statement.

As you have probably noticed, the Java platform provides numerous exception classes. All these classes are descendants of the Throwable class. And all allow programs to differentiate among the various types of exceptions that can occur during the execution of a program.

You also can create your own exception classes to represent problems that can occur within the classes that you write. Indeed, if you are a package developer, you might have to create your own set of exception classes so as to allow your users to differentiate an error that can occur in your package from errors that occur in the Java platform or other packages.

The throw Statement

All methods use the throw statement to throw an exception. The throw statement requires a single argument: a throwable object. Throwable objects are instances of any subclass of the Throwable [1] class. Here's an example of a throw statement:

[1] http://java.sun.com/j2se/1.3/docs/api/java/lang/Throwable.html

throw someThrowableObject;

Let's look at the throw statement in context. The following pop method is taken from a class that implements a common stack object. The method removes the top element from the stack and returns the object:

public Object pop() throws EmptyStackException { Object obj; if (size == 0) { throw new EmptyStackException(); } obj = objectAt(size - 1); setObjectAt(size - 1, null); size--; return obj; }

The pop method checks whether any elements are on the stack. If the stack is empty (its size is equal to 0), pop instantiates a new EmptyStackException object (a member of java.util) and throws it. Later sections in this chapter explain how you can create your own exception classes. For now, all you need to remember is that you can throw only objects that inherit from the java.lang.Throwable class.

Note that the declaration of the pop method contains a throws clause. EmptyStackException is a checked exception, and the pop method makes no effort to catch it. Hence, the method must use the throws clause to declare that it can throw that type of exception.

The Throwable Class and Its Subclasses

The objects that inherit from the Throwable class include direct descendants (objects that inherit directly from the Throwable class) and indirect descendants (objects that inherit from children or grandchildren of the Throwable class). Figure 77 illustrates the class hierarchy of the Throwable class and its most significant subclasses. As you can see, Throwable has two direct descendants: Error and Exception.

Figure 77. The Throwable class and its most significant subclasses.

Errors

When a dynamic linking failure or other "hard" failure in the Java Virtual Machine occurs, the virtual machine throws an Error. Typical programs should not catch Errors. Also, it's unlikely that typical programs will ever throw Errors.

Exceptions

Most programs throw and catch objects that derive from the Exception class. An Exception indicates that a problem occurred, but it is not a serious system problem. Most programs you write will throw and catch Exceptions (as opposed to Errors).

The Exception class has many descendants defined in the Java platform. These descendants indicate various types of exceptions that can occur. For example, IllegalAccessException signals that a particular method could not be found, and NegativeArraySizeException indicates that a program attempted to create an array with a negative size.

One Exception subclass has special meaning: RuntimeException. RuntimeExceptions are exceptions that occur within the Java Virtual Machine during runtime. An example of a runtime exception is NullPointerException, which occurs when a method tries to access a member of an object through a null reference. The section Runtime ExceptionsThe Controversy (page 260) discusses why typical programs shouldn't throw runtime exceptions or subclass RuntimeException.

Creating Your Own Exception Classes

When faced with choosing the type of exception to throw, you can either use one written by someone elsethe Java platform provides a lot of exception classes that you can useor you can write one of your own. You should write your own exception classes if you answer yes to any of the following questions. Otherwise, you can probably use someone else's.

Suppose you are writing a linked list class that you're planning to distribute as freeware. Your linked list class supports the following methods, among others:

objectAt(int n)

Returns the object in the nth position in the list. Throws an exception if the argument is less than 0 or larger than the number of objects currently in the list.

firstObject()

Returns the first object in the list. Throws an exception if the list contains no objects.

indexOf(Object o)

Searches the list for the specified Object and returns its position in the list. Throws an exception if the object passed into the method is not in the list.

The linked list class can throw multiple exceptions, and it would be convenient to be able to catch all exceptions thrown by the linked list with one exception handler. Also, if you plan to distribute your linked list in a package, all related code should be packaged together. Thus, the linked list should provide its own set of exception classes.

Figure 78 illustrates one possible class hierarchy for the exceptions thrown by the linked list.

Figure 78. A possible class hierarchy for the exceptions thrown by a linked list.

LinkedListException is the parent class of all the possible exceptions that can be thrown by the linked list class. Users of the linked list class can write a single exception handler to handle all linked list exceptions with a catch statement like this:

catch (LinkedListException) { ... }

Alternatively, users could write more specialized handlers for each subclass of LinkedListException.

Choosing a Superclass

Any Exception subclass can be used as the parent class of LinkedListException. However, a quick perusal of those subclasses shows that they are inappropriate because they are either too specialized or completely unrelated to LinkedListException. Therefore, the parent class of LinkedListException should be Exception.

Most applets and applications that you write will throw objects that are Exceptions. Errors are reserved for serious, hard errors in the system, such as those that prevent the Java Virtual Machine from running. These are not errors in your program.

Note

For readable code, it's good practice to append the string Exception to the names of all classes that inherit (directly or indirectly) from the Exception class.

Категории