public void go(){ throw new IOException(); }The compiler says:
Dummy.java:15: unreported exception java.io.IOException; must be caught or declared to be thrown throw new IOException(); ^ 1 errorHowever, if you declare it to be thrown in the method declaration, like this:
public void go() throws IOException{ throw new IOException(); }then it compiles successfully. But is it possible to throw a checked exception WITHOUT declaring it to be thrown? You could wrap it in a RuntimeException (for example,
new RuntimeException(new IOException()
), but then you lose the ability to catch the checked exception in the caller method, because you have changed the type of the exception.
There is another trick you can use. I first noticed this being done in the JDK's java.lang.Class#newInstance0
method:
private T newInstance0() throws InstantiationException, IllegalAccessException { ... // Run constructor try { return tmpConstructor.newInstance((Object[])null); } catch (InvocationTargetException e) { Unsafe.getUnsafe().throwException(e.getTargetException()); // Not reached return null; } ... }As shown above, the method throws an
InvocationTargetException
but only declares the exceptions InstantiationException
and IllegalAccessException
to be thrown! The Sun utility class sun.misc.Unsafe
is being used to throw a checked exception without declaring it. We could use the same approach, but unfortunately our code throws a security exception when we try to use it: java.lang.SecurityException: Unsafe
. However, we can bypass this by using reflection to get hold of the unsafe variable directly, as shown below:
public void go() { getUnsafe().throwException(new IOException()); } private Unsafe getUnsafe() { try { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); return (Unsafe) field.get(null); } catch (Exception e) { throw new RuntimeException(e); } }So, why did the JDK developers do it this way? I don't know, but I'm sure they had a good reason. Although this is a neat trick to impress your friends, I wouldn't recommend using it. This is non-standard, undocumented, Sun-specific code which could change in future releases and may not be compatible with all JVMs. It also makes code harder to understand for others and violates the POLA. Further Reading:
Avoiding Checked Exceptions [O'Reilly]
Hi Fahd,
ReplyDeleteWhat JDK version did you use for this example?
I'm now using 1.6.0_21
The method getUnsafe() has explicity declared return type "Unsafe". And the compiler prohibits me to refer to (or import) this type
Iurii Volchyn
iurii.volchyn@gmail.com
Hi Fahd,
ReplyDeleteI've found out that I've got the compiler-time error because I've used the Eclipse's excetion environment instead of the "plain" JDK.
When I updated my settings your example started to work fine.
Thank you very much for your example.
Regards,
Iurii Volchyn
iurii.volchyn@gmail.com