next up previous
Next: 2. Object-Oriented Data Structures Up: 1.11 Unusual Situations versus Previous: 1.11.2 Using Java Exceptions


1.11.3 Exception Handling

If the evaluation of a Java statement generates an exception, that exception can be caught (consumed) and processed by an appropriate handler associated with the statement. The handler typically restores the program to a recoverable state.

The Java construct for associating exception handlers with program statements is called a try-catch block. It has the following syntax

try {
$statement_1$;
$...$
$statement_m$;
}
catch( $ExceptionType_1$ e) { $handler_1$ }
$...$ catch( $ExceptionType_n$ e) { $handler_n$ }
This statement associates the handlers described by $handler_1$, $...$, $handler_n$ with the statements in the sequence
$statement_1$; $... statement_m$;
If any statement in this sequence generates an exception $e$, it is matched against the types $ExceptionType_1$, $...$, $ExceptionType_n$ in order. The handler code for the first type containing $e$ is executed and the exception $e$ is consumed. Then execution resumes at the statement immediately following the try-catch block. If no type in the catch clauses matches the generated exception $e$, program execution searches back up the chain of pending method calls until it finds the next ``youngest'' pending try-catch block with a matching catch clause. If this search exhausts the chain of pending method calls, the Java Virtual Machine prints an error message, a traceback of method calls from the point of exception generation, and aborts program execution.

Since the exception is consumed by the matching catch clause, the program text surrounding the try-catch block does not see the exception. More generally, if a try-catch block includes a catch clause for exception type $E$, the surrounding program text can never see an exception of type $E$ emerge from the try block. As a result, if the exception type $E$ is checked, the containing method need not declare a throws clause for type $E$ unless other code, unshielded by an enclosing try-catch block, can generate exceptions of type $E$.

A try/catch block can optionally be followed by a finally clause

finally {
$cleanUp$
}
This clause is always executed when the try block terminates (including any required handler code). It typically contains code to perform any clean up that might be necessary after executing the statement sequence enclosed by the try/catch block, regardless of whether the statement sequence generates an exception. In other words, the finally clause is always executed (assuming the statement sequence does not loop infinitely). The most common usage of the finally clause is to release a explicitly allocated resource such as an opened file.

We illustrate the use of the try-catch-finally block by the following example. Suppose the main method of the ArithExpr class contains test code for expression evaluation. The main method can protect itself from the exceptions eval might throw by enclosing its invocation in a try-catch block as follows:

ArithExpr a = ...;           // set the expression
Env.e  = ...;                // set up the environment

...
try {                        // try the operation that might fail
  ...
  result = a.eval(e);
  ...
}
catch (UnboundException u) { // handle any error that occurred
  System.out.println ("Unbound exception thrown: " + u.varName +
                      " is undefined.");
}
finally {                    // optional clean-up
  ...
}
...                          // continue with processing
The operation that might throw the exception, eval, is placed inside a try block, and the handling code for the exception appears in a following catch block. There may be more than one catch block, each for a different type of exception. The type and a name for the caught exception is declared at the top of the catch block, and the code in the block can use the exception's fields to perform some kind of error recovery. Here this recovery is simply printing a message that describes the problem.

The finally clause would be useful if the try block read each expression a from a separate file and eval could throw other exceptions besides UnboundException. In this case, the finally clause could close the file regardless of how execution of the try block terminated.

If the code in the try block raises no exceptions, or raises an exception that matches a catch clause, execution continues immediately after the try-catch block and optional finally clause. Of course, the finally clause is executed as part of the try-catch block.


next up previous
Next: 2. Object-Oriented Data Structures Up: 1.11 Unusual Situations versus Previous: 1.11.2 Using Java Exceptions
Corky Cartwright 2003-07-07