是的,有一种方法可以编写一种方法来避免包装检查的异常。对于这个用例,它是一个完美的匹配,虽然你绝对应该非常小心它,因为它很容易混淆初学者。这里是:
@SuppressWarnings("unchecked")
public static <T extends Throwable> void sneakyThrow(Throwable t) throws T {
throw (T) t;
}
你会用它作为
catch (Throwable t) { sneakyThrow(t); }
正如 Joachim Sauer 所评论的,在某些情况下,它有助于让编译器相信行调用sneakyThrow
会导致方法终止。我们可以改变声明的返回类型:
@SuppressWarnings("unchecked")
public static <T extends Throwable> T sneakyThrow(Throwable t) throws T {
throw (T) t;
}
并像这样使用它:
catch (Throwable t) { throw sneakyThrow(t); }
出于教育目的,很高兴看到字节码级别发生了什么。相关片段来自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 // <T:Ljava/lang/Throwable;>(Ljava/lang/Throwable;)Ljava/lang/RuntimeException;^TT;
注意没有checkcast
说明。该方法甚至合法地声明为 throw T
,它可以是 any Throwable
。