方法一:
This post by Alexey Ragozin 描述了如何使用泛型技巧来引发未声明的检查异常。从那个帖子:
public class AnyThrow {
public static void throwUnchecked(Throwable e) {
AnyThrow.<RuntimeException>throwAny(e);
}
@SuppressWarnings("unchecked")
private static <E extends Throwable> void throwAny(Throwable e) throws E {
throw (E)e;
}
}
这个技巧依赖于 throwUnchecked 向编译器“撒谎”类型 E 是 RuntimeException 并调用 throwAny。由于throwAny 被声明为throws E,编译器认为特定的调用可以直接抛出RuntimeException。当然,这个技巧是通过throwAny 任意声明E 并盲目地转换为它来实现的,允许调用者决定它的参数被转换为什么 - 理智编码时的糟糕设计。在运行时,E 是 erased,没有任何意义。
正如你所说,做这样的事情是一个巨大的黑客,你应该很好地记录它的使用。
方法二:
您也可以为此使用sun.misc.Unsafe。首先,您必须实现一个使用反射来返回该类的实例的方法:
private static Unsafe getUnsafe() {
try {
Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeField.setAccessible(true);
return (Unsafe)theUnsafeField.get(null);
}
catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
这是必要的,因为调用 Unsafe.getUnsafe() 通常会抛出 SecurityException。一旦你有了Unsafe 的实例,你就可以使用它的可怕功能:
Unsafe unsafe = getUnsafe();
unsafe.throwException(new Exception());
致谢 this answer 在帖子 https://stackoverflow.com/questions/5574241/interesting-uses-of-sun-misc-unsafe。我想我会为了完整性而提到这一点,但最好只使用上面的技巧而不是允许 Unsafe 进入你的代码。
方法三:
在有关使用 Unsafe、@bestsss points out 的链接答案的 cmets 中,使用已弃用的方法 Thread.stop(Throwable) 是一个更简单的技巧:
Thread.currentThread().stop(new Exception());
在这种情况下,您将使用@SuppressWarnings("deprecation") 并再次非常激烈地记录。同样,我更喜欢第一个技巧,因为它的(相对)清洁度。