Yes, there is a way to write a method that avoids the transfer of checked exceptions. It is ideal for this use case, although you should definitely be very careful with it, as it can easily confuse the uninitiated. Here it is:
@SuppressWarnings("unchecked") public static <T extends Throwable> void sneakyThrow(Throwable t) throws T { throw (T) t; }
and you would use it as
catch (Throwable t) { sneakyThrow(t); }
As Joachim Sauer commented, in some cases this helps convince the compiler that the line calling sneakyThrow will end the method. We can simply change the declared return type:
@SuppressWarnings("unchecked") public static <T extends Throwable> T sneakyThrow(Throwable t) throws T { throw (T) t; }
and use it like this:
catch (Throwable t) { throw sneakyThrow(t); }
For educational purposes, it's nice to see what happens at the bytecode level. Relevant snippet from javap -verbose UncheckedThrower :
public static <T extends java.lang.Throwable> java.lang.RuntimeException sneakyThrow(java.lang.Throwable) throws T; descriptor: (Ljava/lang/Throwable;)Ljava/lang/RuntimeException; flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: athrow Exceptions: throws java.lang.Throwable Signature: #13
Please note that there are no checkcast instructions. The method even legitimately announces to cast T , which can be any Throwable .
source share