当您的方法签名不允许抛出异常时,如何抛出异常? [英] How to throw an Exception when your method signature doesn't allow to throw Exception?

查看:975
本文介绍了当您的方法签名不允许抛出异常时,如何抛出异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样的方法:

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆