it is with great delight that i announce (formally) that

Bob "crazybob" Lee is our Friday Free Stuff winner!
in addition to being exceptionally clever, Bob is the man behind dynaop, the world's easiest, most practical proxy-based Aspect-Oriented Programming (AOP) framework. It enhances Object-Oriented (OO) design in the areas of code reuse, decomposition, dependency reduction. It's a java.net project. Find out more.
please join me in congratulating Bob!
can i just press the pause button for a minute, you guys.
Dr. Josh Bloch and Dr. Neal Gafter (Click and Hack) are total rock stars. But they also happen to be some of the nicest people you will ever meet. seriously. at the end of the day, these guys are just super nice guys. it's a MaryMaryQuiteContary personal testimonial, people. can you feel the love?
ok... we can un-click the pause button...
sooooo ... what you've all been waiting for... here's the answer to the Puzzler:
On Friday, Click and Hack presented a tricky puzzler. You were asked to write a static method that did exactly what the throw statement does, without any exception checking. In other words, it allows you to throw any exception, checked or unchecked, from any point in the code. It's easy to do this using the deprecated Thread.stop(Throwable) method, but the puzzler was to do it without using any deprecated methods.
Bob "crazybob" Lee submitted a correct solution that takes advantage of the fact that Class.newInstance is poorly designed. To quote from the JDK 5.0 RC documentation for this method:
Note that this method propagates any exception thrown by the nullary constructor, including a checked exception. Use of this method effectively bypasses the compile-time exception checking that would otherwise be performed by the compiler. The Constructor.newInstance method avoids this problem by wrapping any exception thrown by the constructor in a (checked) InvocationTargetException.Perhaps Class.newInstance should be deprecated too, but it's too late for that now. Anyway, once you're aware of the method's shortcomings, it's a reasonably simple matter to solve the puzzler. Our solution differs from Bob's primarily in that ours doesn't have a memory leak. In fairness to Bob, Hack would like to point out that Click's original solution had a memory leak in it too, and Hack had to set him straight:
public class Thrower {
private static Throwable throwable;
private Thrower() throws Throwable {
throw throwable;
}
public static synchronized void sneakyThrow(Throwable throwable) {
Thrower.throwable = throwable;
try {
Thrower.class.newInstance();
} catch (InstantiationException e) {
throw new IllegalArgumentException();
} catch (IllegalAccessException e) {
throw new IllegalArgumentException();
} finally {
Thrower.throwable = null; // Avoid memory leak
}
}
}
To test for yourself that this method behaves as advertised, run the following sample program:
public class Test {
public static void main(String[] args) {
Thrower.sneakyThrow(new Exception("Ouch"));
}
}
As Kris Schneider pointed out, this method does not allow you to throw IllegalAccessException or InstantiationException, but this is a minor nit. To a first approximation, it allows you to evade all exception checking.
As we mentioned when we gave the puzzler, there's a completely different way to solve it in Tiger (JDK 5.0). The Tiger solution takes advantage of the fact that generics are not type-checked at run time:
class TigerThrower<T extends Throwable> {
private void sneakyThrow2(Throwable t) throws T {
throw (T) t; // Unchecked cast!!!
}
public static void sneakyThrow(Throwable t) {
new TigerThrower<Error>().sneakyThrow2(t);
}
}
This program will generate a warning when you compile it:
Note: TigerThrower.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details.This is the compiler's way of telling you that you may be shooting yourself in the foot, and in fact you are. If you recompile with -Xlint:unchecked as per the compiler's suggestion it will flag the line with the unchecked cast. The lesson is simple: pay attention to compiler warnings.
and that's all we've got for today, folks.
big kiss!
mary


