Exceptions: When Things Go Wrong
10.4 Handling Exceptions Within a Program Exception Propagation: Searching for a Catch Block
Exception Propagation: Searching for a Catch Block
When an exception is thrown, Java uses both static and dynamic scoping to find a catch clause to handle it. Java knows how the program is
defined—after all, it compiled it. Thus, the static scope of a program’s
methods is determined by the compiler. Java also places a record of every
method call the program makes on a method call stack. A method call stack is a data structure that behaves like a stack of dishes in the cafeteria.
For each method call, a method call block is placed on top of the stack (like
a dish), and when a particular method call returns, its block is removed
from the top of the stack (Fig. 10.12).
An important feature of the method call stack is that the current executing method is always represented by the top block on the method
call stack. If an exception happens during that method call, you can trace
backward through the method calls, if necessary, to find an exception handler for that exception. In Figure 10.12, you can visualize this backtrace
as a matter of reversing the direction of the curved arrows.
In order to find a matching catch block for an exception, Java uses
its knowledge of the program’s static and dynamic scope to perform a
method stack trace. The basic idea is that Java traces backward through the program until it finds an appropriate catch clause. The trace begins
within the block that threw the exception. Of course, one block can be
nested (statically) within another block. If the exception is not caught by
the block in which it is thrown, Java searches the enclosing block. This is
static scoping. If it is not caught within the enclosing block, Java searches
the next higher enclosing block, and so on. This is still static scoping.
If the exception is not caught at all within the method in which it was
thrown, Java uses the method call stack (Fig. 10.12) to search backward
through the method calls that were made leading up to the exception.
This is dynamic scoping. In the case of our CalcAvgTest() example
(Fig. 10.7), Java would search backward to the CalcAvgTest.main()
method, which is where avgFirstN() was called, and it would find
the catch clause there for handling IllegalArgumentExceptions.
SELF-STUDY EXERCISES
EXERCISE 10.3 Suppose a program throws an ArrayIndexOutOfBoundsException. Using the exception hierarchy in Figure 10.4, determine which of the following catch clauses could handle that exception.
a. catch (RunTimeException e)
b. catch (StringIndexOutOfBoundsException e)
c. catch (IndexOutOfBoundsException e)
d. catch (Exception e)
e. catch (ArrayStoreException e)
EXERCISE 10.5 For the values returned by random() in the previous exercise, show what would be output if printStackTrace() were called in addition to printing an error message.
EXERCISE 10.6 In the MyClass2 program, suppose that the first time random() is called it returns 0.44, and the second time it is called it returns 0.98. What output would be printed by the program?
EXERCISE 10.7 For the values returned by random() in the previous exercise, show what would be output if printStackTrace() were
called instead of printing an error message.
EXERCISE 10.8 Find the divide-by-zero error in the following program, and then show what stack trace would be printed by the program:
EXERCISE 10.9 Modify method2() so that it handles the divide-byzero exception itself, instead of letting Java handle it. Have it print an error message and a stack trace.
EXERCISE 10.10 What would be printed by the following code segment if someValue equals 1000?
EXERCISE 10.11 What would be printed by the code segment in the preceding question if someValue equals 50?
EXERCISE 10.12 Write a try/catch block that throws an Exception
if the value of variable X is less than zero. The exception should be an
instance of Exception and, when it is caught, the message returned by
getMessage() should be “ERROR: Negative value in X coordinate.”