Java Reference
In-Depth Information
Multiple catch Blocks
If a
try
block can throw several different kinds of exception, you can put several
catch
blocks after the
try
block to handle them:
try {
// Code that may throw exceptions
} catch(ArithmeticException e) {
// Code for handling ArithmeticException exceptions
} catch(IndexOutOfBoundsException e) {
// Code for handling IndexOutOfBoundsException exceptions
}
// Execution continues here...
Exceptions of type
ArithmeticException
are caught by the first
catch
block, and exceptions of type
IndexOutOfBoundsException
are caught by the second. Of course, if an
ArithmeticException
is thrown,
only the code in that
catch
block is executed. When it is complete, execution continues with the statement
following the last
catch
block.
When you need to catch exceptions of several different types that may be thrown in a
try
block, the order
of the
catch
blocks can be important. When an exception is thrown, it is caught by the first
catch
block
that has a parameter type that is the same as that of the exception, or a type that is a superclass of the type
of the exception. An extreme case would be if you specified the
catch
block parameter as type
Exception
.
This would catch any exception that is of type
Exception
, or of a class type that is derived from
Exception
.
This includes virtually all the exceptions you are likely to meet in the normal course of events.
This has implications for multiple
catch
blocks relating to exception class types in a hierarchy. The
catch
blocks must be in sequence with the most derived type first and the most basic type last. Otherwise,
your code does not compile. The simple reason for this is that if a
catch
block for a given class type precedes
a
catch
block for a type that is derived from the first, the second
catch
block can never be executed, and
the compiler detects that this is the case.
Suppose you have a
catch
block for exceptions of type
ArithmeticException
and another for excep-
tions of type
Exception
as a catch-all. If you write them in the following sequence, exceptions of type
ArithmeticException
could never reach the second
catch
block because they are always caught by the
first:
// Invalid catch block sequence - won't compile!
try {
// try block code
} catch(Exception e) {
// Generic handling of exceptions
} catch(ArithmeticException e) {
// Specialized handling for these exceptions
}
Of course, this wouldn't get past the compiler — it would be flagged as an error.
In principle, if you're only interested in generic exceptions, all the error handling code can be localized
in one
catch
block for exceptions of the superclass type. However, in general it is more useful and better