What is happening here?
This code circumvents Compile-Time Checking of Exceptions.
Why it can be useful?
It is not always convenient to work with api that uses checked exceptions.
One of the most famous examples is JDBC. Working with jdbc always requires the developer to deal with SQLException
. But usually you don't know what you should do with the exception.
Or if you're working with library where the developers decided to inherit their exceptions from Exception
rather than RuntimeException
.
Why checked child of IOException
(RemoteException
) gets converted to RuntimeException
?
It is not converted to a RuntimeException
.
The thrown exception is RemoteException
:
Exception in thread "main" java.rmi.RemoteException: go unchecked!
The code snippet uses Java generics "tricks". Without the @SuppressWarnings("unchecked")
line the compiler would generate an unchecked cast warning.
Puzzle 43
The code snippet is one of the solutions of Puzzle 43 of Java Puzzlers: Traps, Pitfalls, and Corner Cases:
// Don’t do this - circumvents exception checking!
public static void sneakyThrow(Throwable t) {
Thread.currentThread().stop(t); // Deprecated!!
}
It is possible to write a method that is functionally equivalent to sneakyThrow
without using any deprecated methods. In fact, there are at least two ways to do it.
One of them works only in release 5.0 and later releases. Can you write such a
method? It must be written in Java, not in JVM bytecode. You must not change the
method after its clients are compiled. Your method doesn’t have to be perfect: It is
acceptable if it can’t throw one or two subclasses of Exception
.
Solution from the book using generics:
// 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;
}
}
Note on this solution from the book:
A warning is the compiler’s way of telling you that you may be shooting yourself
in the foot, and in fact you are. The unchecked cast warning tells you that the
cast in question will not be checked at run time. When you get an unchecked
cast warning, modify your program to eliminate it, or convince yourself that
the cast cannot fail
In summary, Java’s exception checking is not enforced by the virtual
machine. It is a compile-time facility designed to make it easier to write correct
programs, but it can be circumvented at run time. To reduce your exposure, do not
ignore compiler warnings.
See also:
@SneakyThrows