如何抛出一个异常,当你的方法签名不允许抛出异常?(How to throw an Exception

2019-07-30 23:14发布

我有这样的方法:

public void getSomething(){
...
}

我想抛出一个ExceptiongetSomething() 编译器将不允许我这样做,因为我的方法不允许Exception在那里被抛出。 但我需要抛出的子类Exception为我的测试(我不能把未经检查的Exception )。 这显然是一个黑客,但我需要为我的测试。 我尝试了EasyMock,但它不允许我这样做,要么。 任何想法如何做到这一点?

谢谢,肖恩·阮

Answer 1:

方法1:

本帖由阿列克谢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 “说谎”到编译器的类型ERuntimeException ,其调用throwAny 。 由于throwAny被声明为throws E ,编译器认为,特定的呼叫可以随便扔RuntimeException 。 当然,关键是通过成为可能throwAny任意声明E盲目铸造它,允许调用者决定什么它的参数被转换为-三立编码时,可怕的设计。 在运行时, E被删除 ,并没有任何意义。

正如你提到的,在做这样的事情是一个巨大的黑客,你应该记录它的使用非常好。


方法2:

您还可以使用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());

幸得此答案的帖子https://stackoverflow.com/questions/5574241/interesting-uses-of-sun-misc-unsafe 。 我想我会提到这一点的完整性,但它可能只是为了更好地使用上述伎俩,而不是允许Unsafe到你的代码。


方法3:

在有关使用链接的答案的评论Unsafe , @bestsss指出使用过时的方法更简单的伎俩Thread.stop(Throwable)

Thread.currentThread().stop(new Exception());

在这种情况下,你可以使用@SuppressWarnings("deprecation")并再次记录非常激烈。 同样,我更喜欢它的(相对)清洁第一招。



Answer 2:

Java有两种异常,检查,未经检查的。 您必须声明检查异常,但你不必申报unchecked异常。

RuntimeException是基本未经检查的异常,所以你可以把那未声明的。

public void getSomething(){
   throw new RuntimeException("I don't have to be declared in the method header!");
}

作为一个侧面说明,你可能不想抛出RuntimeException的原料,但它继承更具体的您的需要的东西。 RuntimeException的任何子类,将取消选中为好。



Answer 3:

我不知道你想干什么。 你可以只抛出一个未经检查的异常的方法内,然后测试使用JUnit像下面的示例所示。

public void getSomething() {
    throw new RuntimeException();
}

JUnit 4测试实施例:

@Test
public void testGetSomething() {
    try {
        getSomething();
        fail("Expecting RuntimeException!");
    } catch (Exception e) {
        Logger.getLogger("test").info("Exception was caught: " + e.getClass());
    }
}


文章来源: How to throw an Exception when your method signature doesn't allow to throw Exception?