It is not a matter of IF but WHEN things will go wrong in a computer program. Sometimes there are bugs, errors of one form or another. There are also unforeseen use cases. You can never assume a computer program is perfect. Exception-Handling helps us to catch erroneous events and devise means of correcting them. We discuss this topic here since exception-handling can take more code than should be put into the main line of execution. In such cases, a method in an exception-handling class should be called. Exception handling mechanisms allow a program to continue executing, instead of terminating it abruptly, even if an error occurs in the program.
10.4 Handling Exceptions Within a Program Exception Propagation: Searching for a Catch Block
Trying, Throwing, and Catching an Exception
In Java, errors and other abnormal conditions are handled by throwing and catching exceptions. When an error or an exceptional condition is detected, you can throw an exception as a way of signaling the abnormal condition. This is like pulling
the fire alarm. When an exception is thrown, an exception handler will catch the exception and deal with it (Fig. 10.6). We will discuss try blocks, which typically are associated with catching exceptions, later in the section.
If we go back to our avgFirstN() example, the typical way of handling this error in Java would be to throw an exception in the
avgFirstN() method and catch it in the calling method. Of course, the calling method could be in the same object or it could belong to some other object. In the latter case, the detection of the error is separated from its handling. This division
of labor opens up a wide range of possibilities. For example, a program could dedicate a single object to serve as the handler for all its exceptions. The object would be sort of like the program’s fire department.
To illustrate Java’s try/throw/catch mechanism, let’s revisit the
CalcAvgTest program. The version shown in Figure 10.7 mimics the way Java’s default exception handler works. If the avgFirstN()
method is called with an argument that is zero or negative, an
IllegalArgumentException is thrown. The exception is caught by the catch clause in the CalcAvgTest.main() method.
Let’s go through this example step by step. The first thing to notice is that if the CalcAverage.avgFirstN() method has a zero or negative argument, it will throw an exception:
Note the syntax of the throw statement. It creates a new IllegalArgumentException object and passes it a message that describes the
error. This message becomes part of the exception object. It can be retrieved using the getMessage() method, which is inherited from the
Throwable class (Fig. 10.4).
When a throw statement is executed, the JVM interrupts the normal execution of the program and searches for an exception handler. We will describe the details of this search shortly. In this case, the exception handler
is the catch clause contained in the CalcAvgTest.main() method:
When an IllegalArgumentException is thrown, the statements
within this catch clause are executed. The first statement uses the
getMessage() method to print a copy of the error message. The second statement uses the printStackTrace() method, which is defined
in Throwable and inherited by all Exceptions, to print a trace of the
method calls leading up to the exception. The last statement causes the
program to terminate.
When we run this program, the following output will be generated as
a result of the illegal argument error:
Thus, as in the previous example of Java’s default exception handler, our
exception handler also prints out a description of the error and a trace of
the method calls that led up to the error. However, in this example, we are
directly handling the exception rather than leaving it up to Java’s default
exception handler. Of course, this example is intended mainly for illustrative purposes. It would make little sense to write our own exception
handler if it does nothing more than mimic Java’s default handler.
Finally, note that the catch clause is associated with a try block. The
handling of exceptions in Java takes place in two parts: First, we try to execute some statements, which may or may not lead to an exception.
These are the statements contained within the try clause:
Second, we provide one or more catch clauses to handle particular types of exceptions. In this case, we are only handling
IllegalArgumentExceptions.
As we said earlier, throwing an exception is like pulling a fire alarm.
The throw occurs somewhere within the scope of the try block. The “fire
department” in this case is the code contained in the catch clause that
immediately follows the try block. This is the exception handler for this particular exception. There’s something like a game of catch going on
here: Some method within the try block throws an Exception object,
which is caught and handled by the catch block located in some other
object (Fig. 10.8).