什么是“自我抑制不允许”,为什么Javac生成代码导致这个错误?

这种新的 Java 7 try-with-resources构造是相当不错的.或者至少,这是很好,直到一个例外来了,毁了我的一天.

我终于设法把它烧成一个可重复的测试,它只使用JUnit jMock.

@Test
public void testAddSuppressedIssue() throws Exception {
    Mockery mockery = new Mockery();
    final Dependency dependency = mockery.mock(Dependency.class);

    mockery.checking(new Expectations() {{
        allowing(dependency).expectedCall();
        allowing(dependency).close();
    }});

    try (DependencyUser user = new DependencyUser(dependency)) {
        user.doStuff();
    }
}

// A class we're testing.
private static class DependencyUser implements Closeable {
    private final Dependency dependency;

    private DependencyUser(Dependency dependency) {
        this.dependency = dependency;
    }

    public void doStuff() {
        dependency.unexpectedCall(); // bug
    }

    @Override
    public void close() throws IOException {
        dependency.close();
    }
}

// Interface for its dependent component.
private static interface Dependency extends Closeable {
    void expectedCall();
    void unexpectedCall();
}

运行这个例子,我得到:

java.lang.IllegalArgumentException: Self-suppression not permitted
    at java.lang.Throwable.addSuppressed(Throwable.java:1042)
    at com.acme.Java7FeaturesTest.testTryWithResources(Java7FeaturesTest.java:35)

阅读文档,他们似乎在说,如果要将抑制异常添加到自身,那就是触发此错误.但是我没有这样做,我只是使用一个资源块尝试. Java编译器然后生成似乎是非法代码,这使得该功能无法使用.

当然,当测试通过时,不会发生问题.当测试失败时,会发生异常.所以现在我已经解决了我最初发现我已经恢复使用try-with-resources的问题.但是下一次发生异常时,我宁愿异常是期望失败,而不是一个Java本身已经发出似乎没有好的理由.

那么…有没有办法在这里得到适当的错误报告,而不放弃试用资源?

解决方法

看起来jMock从两个方法都抛出相同的异常实例.没有jMock就可以复制它:
public class Test implements Closeable {
    private RuntimeException ex = new RuntimeException();

    public void doStuff() {
        throw ex;
    }

    public void close() {
        throw ex;
    }
}

try (Test t = new test()) {
    t.doStuff();
}

如果是这样,我认为这是jMock而不是Java编译器的问题.

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...