Java Reference
In-Depth Information
class's parameterless constructor. Therefore, the sneakyThrow method stashes this exception in a
static variable. To make the method thread-safe, it must be synchronized. This causes concurrent
invocations to take turns using the static t field.
Note that the t field is nulled out in a finally block: Just because the method is sneaky doesn't
mean it should also be leaky. If this field weren't nulled out, it would prevent the exception from
being garbage collected. Finally, note that the method will fail with an IllegalArgumentException
if you ask it to throw an InstantiationException or IllegalAccessException . This is an
inherent limitation of the technique.
The documentation for Class.newInstance goes on to say that "the Constructor.newInstance
method avoids this problem by wrapping any exception thrown by the constructor in a (checked)
InvocationTargetException ." Clearly, Class.newInstance should have done the same thing, but
it's far too late to correct this deficiency. Doing so would introduce a source-level incompatibility,
breaking the many programs that depend on Class.newInstance . It would not be practical to
deprecate this method either, because it is so commonly used. Just be aware when you use it that
Class.newInstance can throw checked exceptions that it does not declare.
Generics, which were added in release 5.0, enable a completely different solution to this puzzle. For
maximal compatibility generics are implemented by type erasure : Generic type information is
checked at compile time but not at run time [JLS 4.7]. The following solution exploits this:
// Don't do this either - circumvents exception checking!
class TigerThrower<T extends Throwable> {
public static void sneakyThrow(Throwable t) {
new TigerThrower<Error>().sneakyThrow2(t);
}
private void sneakyThrow2(Throwable t) throws T {
throw (T) t;
}
}
This program will generate a warning when you compile it:
TigerThrower.java:7: warning: [unchecked] unchecked cast
 
 
Search WWH ::




Custom Search