当您的方法签名不允许抛出异常时,如何抛出异常? [英] How to throw an Exception when your method signature doesn't allow to throw Exception?
问题描述
我有一个这样的方法:
public void getSomething(){
...
}
我想在getSomething中抛出异常。编译器不会允许我这样做,因为我的方法不允许在其中抛出异常。但是我需要抛出一个异常的子类来测试(我不能抛出未检查的异常)。这显然是一个黑客,但我需要它来进行测试。我试过EasyMock,但也不允许我这么做。任何想法如何做?
谢谢,
Sean Nguyen
方法1:
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)抛出E {
throw(E)e;
}
}
该技巧依赖于 throwUnchecked
说谎到编译器,类型 E
是 RuntimeException
,其调用 throwAny
。由于 throwAny
被声明为 throws E
,编译器认为特定的调用可以抛出 RuntimeException
。当然,这个伎俩可以通过 throwAny
任意声明 E
并盲目投射,允许来电者决定它的论据是什么 - 在编写正确的时候可怕的设计。在运行时, E
是删除并没有任何意义。
正如你所说,做这样的事情是一个巨大的黑客,你应该很好地记录其使用。 p>
方法2:
也可以使用 sun.misc.Unsafe
为此目的。首先,您必须实现一种使用反射来返回该类的实例的方法:
private static Unsafe getUnsafe(){
尝试{
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 = getUnsafe();
unsafe.throwException(new Exception());
信用转到这个答案在发布的 https://stackoverflow.com/questions / 5574241 /有趣的用途 - 的 - 太阳MISC-不安全。我以为我会提到这是完整的,但是最好只是使用上面的技巧,而不是允许不安全
到您的代码。
方法3:
在关于使用 Unsafe
的链接答案的评论中, @ bestsss指出使用不推荐的方法 Thread.stop(Throwable)
:
Thread.currentThread()。stop(new Exception());在这种情况下,您将使用 @SuppressWarnings(deprecation) code>再次非常激烈的文件。再次,我更喜欢其(相对)清洁的第一个技巧。
I have a method like this:
public void getSomething(){
...
}
I want to throw an exception inside getSomething. The compiler will not allow me to do that because my method doesn't allow Exception to be thrown in there. But I need to throw a subclass of Exception for my testing (I can't throw Unchecked exception). This is clearly a hack but I need it for my testing. I tried EasyMock but it doesn't allow me to do that either. Any ideas how to do that?
Thanks,
Sean Nguyen
解决方案 Method 1:
This post by Alexey Ragozin describes how to use a generics trick to throw an undeclared checked exception. From that post:
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;
}
}
The trick relies on throwUnchecked
"lying" to the compiler that the type E
is RuntimeException
with its call to throwAny
. Since throwAny
is declared as throws E
, the compiler thinks that particular call can just throw RuntimeException
. Of course, the trick is made possible by throwAny
arbitrarily declaring E
and blindly casting to it, allowing the caller to decide what its argument is cast to - terrible design when coding sanely. At runtime, E
is erased and has no meaning.
As you noted, doing such a thing is a huge hack and you should document its use very well.
Method 2:
You can also use sun.misc.Unsafe
to this end. First you must implement a method that uses reflection to return that class's instance:
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);
}
}
This is necessary as calling Unsafe.getUnsafe()
will typically throw a SecurityException
. Once you have the instance of Unsafe
you can put its terrifying capabilities to use:
Unsafe unsafe = getUnsafe();
unsafe.throwException(new Exception());
Credit goes to this answer on the post https://stackoverflow.com/questions/5574241/interesting-uses-of-sun-misc-unsafe. I thought I'd mention this for completeness but it's probably better just to use the trick above instead of allowing Unsafe
into your code.
Method 3:
In the comments of the linked answer about using Unsafe
, @bestsss points out a much simpler trick using the deprecated method Thread.stop(Throwable)
:
Thread.currentThread().stop(new Exception());
In this case you would use @SuppressWarnings("deprecation")
and once again document very fiercely. Again, I prefer the first trick for its (relative) cleanliness.
这篇关于当您的方法签名不允许抛出异常时,如何抛出异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!