|
|
|
Advertisement
|
Summary
This tutorial covers the nuts and bolts of what exceptions are and how they work in the Java language and virtual machine. It discusses exception classes and objects, throwing and catching exceptions, the method invocation stack, thethrowsclause, checked vs. unchecked exceptions, andfinallyclauses.
Exceptions are the customary way in Java to indicate to a calling method that an abnormal condition has occurred. This article is a companion piece to this month's Design Techniques installment, which discusses how to use exceptions appropriately in your programs and designs. Look to this companion article for a tutorial on the nuts and bolts of what exceptions are and how they work in the Java language and virtual machine.
When a method encounters an abnormal condition (an exception condition) that it can't handle itself, it may throw an exception. Throwing an exception is like throwing a beeping, flashing red ball to indicate there is a problem that can't be handled where it occurred. Somewhere, you hope, this ball will be caught and the problem will be dealt with. Exceptions are caught by handlers positioned along the thread's method invocation stack. If the calling method isn't prepared to catch the exception, it throws the exception up to its calling method, and so on. If one of the threads of your program throws an exception that isn't caught by any method along the method invocation stack, that thread will expire. When you program in Java, you must position catchers (the exception handlers) strategically, so your program will catch and handle all exceptions from which you want your program to recover.
Exception classes
In Java, exceptions are objects. When you throw an exception, you throw
an object. You can't throw just any object as an exception, however --
only those objects whose classes descend from Throwable.
Throwable serves as the base class for an entire family of
classes, declared in java.lang, that your program can
instantiate and throw. A small part of this family is shown in Figure
1.
As you can see in Figure 1, Throwable has two direct
subclasses, Exception and Error. Exceptions
(members of the Exception family) are thrown to signal
abnormal conditions that can often be handled by some catcher, though
it's possible they may not be caught and therefore could result in a
dead thread. Errors (members of the Error family) are
usually thrown for more serious problems, such as
OutOfMemoryError, that may not be so easy to handle. In
general, code you write should throw only exceptions, not errors.
Errors are usually thrown by the methods of the Java API, or by the
Java virtual machine itself.
Figure 1. A partial view of the Throwable family
|
In addition to throwing objects whose classes are declared in
java.lang, you can throw objects of your own design. To
create your own class of throwable objects, you need only declare it as
a subclass of some member of the Throwable family. In
general, however, the throwable classes you define should extend class
Exception. They should be "exceptions." The reasoning
behind this rule will be explained later in this article.
Whether you use an existing exception class from java.lang
or create one of your own depends upon the situation. In some cases, a
class from java.lang will do just fine. For example, if
one of your methods is invoked with an invalid argument, you could
throw IllegalArgumentException, a subclass of
RuntimeException in java.lang.
Other times, however, you will want to convey more information about
the abnormal condition than a class from java.lang will
allow. Usually, the class of the exception object itself indicates the
type of abnormal condition that was encountered. For example, if a
thrown exception object has class
IllegalArgumentException, that indicates someone passed an
illegal argument to a method. Sometimes you will want to indicate that a
method encountered an abnormal condition that isn't represented by a
class in the Throwable family of java.lang.
As an example, imagine you are writing a Java program that simulates a customer of a virtual café drinking a cup of coffee. Consider the exceptional conditions that might occur while the customer sips. The class hierarchy of exceptions shown in Figure 2 represents a few possibilities.
Figure 2. Exception hierarchy for coffee sipping |
If the customer discovers, with dismay, that the coffee is cold, your
program could throw a TooColdException. On the other hand,
if the customer discovers that the coffee is overly hot, your program
could throw a TooHotException. These conditions could be
exceptions because they are (hopefully) not the normal
situation in your café. (Exceptional conditions are not
necessarily rare, just outside the normal flow of events.) The code for
your new exception classes might look like this:
// In Source Packet in file except/ex1/TemperatureException.java
class TemperatureException extends Exception {
}
// In Source Packet in file except/ex1/TooColdException.java
class TooColdException extends TemperatureException {
}
// In Source Packet in file except/ex1/TooHotException.java
class TooHotException extends TemperatureException {
}
This family of classes, the TemperatureException family,
declares three new types of exceptions for your program to throw. Note
that each exception indicates by its class the kind of abnormal
condition that would cause it to be thrown:
TemperatureException indicates some kind of problem with
temperature; TooColdException indicates something was too
cold; and TooHotException indicates something was too
hot. Note also that TemperatureException extends
Exception -- not Throwable,
Error, or any other class declared in
java.lang.
|
Sponsored Links
|