问题描述
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
被擦除并且没有任何意义。
如您所述,做这样的事情是一个巨大的漏洞,您应该很好地记录它的使用。
您也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());
值得信赖的是在帖子[http://codingdict.com/questions/4269)上的答案。我以为是出于完整性的考虑而提到了它,但是最好使用上面的技巧而不是允许您的代码进入。Unsafe
在有关使用的链接答案的注释中Unsafe
,@bestsss指出了不建议使用的方法简单得多的技巧Thread.stop(Throwable)
:
Thread.currentThread().stop(new Exception());
在这种情况下,您将@SuppressWarnings("deprecation")
非常猛烈地使用并再次进行记录。同样,我比较喜欢它的(相对)清洁度。
解决方法
我有这样的方法:
public void getSomething(){
...
}
我想抛出一个Exception
内getSomething()
。编译器不允许我这样做,因为不允许Exception
将我的方法扔在那里。但是我需要抛出一个的子类来Exception
进行测试
(我不能抛出UncheckedException
)。显然这是一个hack,但我需要进行测试。我尝试过EasyMock,但它也不允许我这样做。任何想法如何做到这一点?
谢谢,肖恩·阮