7.3 Exception Handling: try, catch, and finally
The mechanism for handling exceptions is embedded in the try-catch-finally construct, which has the following basic form:
try { // try block
statements
} catch (
exception_type
1
parameter
1
) { // uni-catch clause
statements
}
…
catch (
exception_type
n
parameter
n
) { // uni-catch clause
statements
} finally { // finally clause
statements
}
A few aspects about the syntax of this construct should be noted. For each try block, there can be zero or more catch clauses (i.e., it can have multiple catch clauses), but only one finally clause. The catch clauses and the finally clause must always appear in conjunction with a try block, and in the right order. A try block must be followed by at least one catch clause, or a finally clause must be specified—in contrast to the try-with-resources statement where neither a catch nor a finally clause is mandatory (p. 407). In addition to the try block, each catch clause and the finally clause specify a block, { }. The block notation is mandatory.
Exceptions thrown during execution of the try block can be caught and handled in a catch clause. Each catch clause defines an exception handler. The header of the catch clause specifies exactly one exception parameter. The exception type must be of the Throwable class or one of its subclasses; otherwise, the code will not compile. The type of the exception parameter of a catch clause is specified by a single exception type in the syntax shown earlier, and such a catch clause is called a uni-catch clause.
A finally clause is always executed, regardless of the cause of exit from the try block, or whether any catch clause was executed at all. The two exceptions to this scenario are if the JVM crashes or the System.exit() method is called. Figure 7.4 shows three typical scenarios of control flow through the try-catch-finally construct.
Figure 7.4 The try-catch-finally Construct
The try block, the catch clause, and the finally clause of a try-catch-finally construct can contain arbitrary code, which means that a try-catch-finally construct can be nested in any block of the try-catch-finally construct. However, such nesting can easily make the code difficult to read and is best avoided, if possible.