Proposal: Improved Exception Handling for Java
Neal Gafter
neal at gafter.com
Thu Mar 12 11:46:07 PDT 2009
I've updated the "Improved Exception Handling" proposal. The current
rich-text version can be found at
http://docs.google.com/Doc?id=ddb3zt39_76dtz7bsg2
In the "Compatibility" section, I added the following:
"Because the point of the rethrow proposal is to improve the
precision of exception checking, and Java is sensitive to catch
clauses that it determines to be unreachable, the most straightforward
way to make this change fully compatible is to simply remove Java's
requirement that catch clauses be reachable. The requirement could be
eliminated or made a mandatory warning.
"It is a bit harder to support muticatch alone without either
special treatment for final catch parameters or disjunction types.
The simplest way is to disallow assigning to multicatch parameters
(i.e. making them implicitly final), and when they're rethrown use the
types from the catch parameter's declaration as the thrown types for
exception analysis. This would not be a breaking change, but would be
more likely to create a breaking change later if special treatment for
final catch clauses were added."
I've also added the following tutorial material to the "advanced
example" section:
ADVANCED EXAMPLE:
Catching Multiple Exception Types
Sometimes you need to handle one of several exception types with the same code:
try {
return klass.newInstance();
} catch (InstantiationException e) {
throw new AssertionError(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
One alternative is to find a common supertype of these exceptions and
catch just that type:
// Broken - catches exceptions that should be allowed to propagate!
try {
return klass.newInstance();
} catch (Exception e) {
throw new AssertionError(e);
}
Unfortunately, that can catch more exceptions than you intend. In
this example, it wraps all unchecked exceptions in AssertionError.
This proposal makes it possible to catch two or more exception types
in a single catch clause:
try {
return klass.newInstance();
} catch (final InstantiationException | IllegalAccessException e) {
throw new AssertionError(e);
}
Improved Checking for Rethrown Exceptions
Occasionally you need to intercept all exceptions, do something with
them, and allow them to propogate. Doing this today is awkward. One
way is to catch Throwable. But how do you rethrow it, without
declaring Throwable in the current method and everything above it on
the call stack?
try {
doable.doIt(); // Specified to throw several different exceptions
} catch (Throwable ex) {
logger.log(ex);
throw ex; // Won't compile unless method is specified to
throw Throwable!
}
Because this code throws an expression whose dynamic type is
Throwable, the compiler currently thinks that the throw statement can
throw any checked exception type. Java Puzzlers describes a couple of
ways of rethrowing an exception such that the compiler's exception
checking is circumvented. Some folks would resort to secret sun.Misc
APIs. Some programmers wrap the exception prior to rethrowing it:
try {
doable.doIt();
} catch (Throwable ex) {
logger.log(ex);
throw new WrappedException(ex); // Obscures exception type!
}
Unfortunately, this approach wraps all checked as well as unchecked
exceptions. We really want the rethrown exception to be treated as if
this try-finally block can only throw checked exceptions that are
thrown in the try block.
If a caught exception is declared final, it is safe to rethrow any
caught exception:
try {
doable.doIt();
} catch (final Throwable ex) {
logger.log(ex);
throw ex;
}
Because the catch parameter is final, it can only hold exceptions that
are thrown from the try block. This proposal enables exception
checking to take advantage of that fact: a rethrown final catch
parameter is treated as if it throws only exceptions that occur in the
try block.
More information about the coin-dev
mailing list