为什么try..finally阻止不将原始异常注册为抑制?

[英]Why does try..finally block not register the original exception as suppressed?


With the following code:

使用以下代码:

try {
    throw new RuntimeException ("main");
}
finally {
    throw new RuntimeException ("finally");
}

I get this result:

我得到这个结果:

Exception in thread "main" java.lang.RuntimeException: finally
        at test.main(test.java:12)

However, with the addition of suppressed exceptions in Java 7, wouldn't it be logical for the language to register original "main" exception as suppressed when finally block itself fails with exception? Currently I have to manually emulate this:

但是,通过在Java 7中添加抑制的异常,当最终块本身因异常而失败时,将原始“主”异常注册为抑制的语言是否合乎逻辑?目前我必须手动模拟这个:

try {
    throw new RuntimeException ("main");
}
catch (RuntimeException exception) {
    try {
        throw new RuntimeException ("finally");
    }
    catch (RuntimeException exception2) {
        exception2.addSuppressed (exception);
        throw exception2;
    }
}

to receive more useful (for understanding what's going on) result:

获得更多有用的(用于了解正在发生的事情)结果:

Exception in thread "main" java.lang.RuntimeException: finally
        at test.main(test.java:13)
        Suppressed: java.lang.RuntimeException: main
                at test.main(test.java:9)

EDIT: To clarify what I'm wondering. Current Java version is 8, suppressed exceptions are not a brand new feature. But try..finally still doesn't incorporate them. Is there something that prevents this from happening?

编辑:澄清我在想什么。目前的Java版本是8,抑制异常不是一个全新的功能。但是试试..最后仍然没有加入它们。有什么东西阻止这种情况发生吗?

2 个解决方案

#1


8  

Because try-with-resources is syntactic sugar and the Java compiler doesn't expand regular try-finally blocks in the same way.

因为try-with-resources是语法糖,Java编译器不会以相同的方式扩展常规的try-finally块。

Take a look at the following code:

看一下下面的代码:

try(FileInputStream fstream = new FileInputStream("test")) {
    fstream.read();
}

When compiled and then decompiled (using IntelliJ IDEA) it looks like this:

编译然后反编译(使用IntelliJ IDEA)时,它看起来像这样:

FileInputStream fstream = new FileInputStream("test");
Throwable var2 = null;

try {
    fstream.read();
} catch (Throwable var19) {
    var2 = var19;
    throw var19;
} finally {
    if(fstream != null) {
        if(var2 != null) {
            try {
                fstream.close();
            } catch (Throwable var17) {
                var2.addSuppressed(var17);
            }
        } else {
            fstream.close();
        }
    }
}

Whereas this code:

而这段代码:

FileInputStream fstream = new FileInputStream("test");
try {
    fstream.read();
} finally {
    fstream.close();
}

Looks exactly the same when compiled and decompiled.

编译和反编译时看起来完全相同。

Now, the case could definitely be made that all finally blocks should be expanded in the same way as is done above, but for some reason that has either been overlooked or decided against.

现在,绝对可以确保所有最终块都应该以与上面相同的方式进行扩展,但由于某些原因,这些块被忽略或决定反对。

I suggest you open a feature request for this because I think it's a sensible feature.

我建议你打开一个功能请求,因为我认为这是一个明智的功能。

#2


5  

This isn't an authoritative answer but it looks like such a change would either break compatibility, or try-with-resources and try-finally would be inconsistent with each other.

这不是一个权威性的答案,但看起来这样的改变会破坏兼容性,或者尝试使用资源和try-finally会彼此不一致。

The semantics in try-with-resources is that the exception thrown from the try block is propagated, with the exception thrown when invoking the close() method registered as suppressed. This makes sense from a practical point of view, you want to catch your "real" exception and then maybe also deal with the resource not closing if you want to.

try-with-resources中的语义是传播try块抛出的异常,并在调用注册为suppress的close()方法时抛出异常。从实际的角度来看,这是有道理的,您希望捕获“真正的”异常,然后如果您愿意,也可以处理未关闭的资源。

But in try-finally it is the exception thrown in finally that is propagated (while the one from try is "swallowed") and therefore we have a choice of three bad solutions:

但是在try-finally中,最终抛出的异常被传播(而try中的那个被“吞噬”),因此我们可以选择三种不好的解决方案:

  1. Reverse the logic of try-finally to align it with try-with-resources and ruin code (or rather, bug) compatibility with all previous code.
  2. 颠倒try-finally的逻辑,使其与try-with-resources和破坏代码(或者更确切地说,bug)兼容所有以前的代码。

  3. Keep propagating the "close()" exception with the try exception registered as suppressed, making the two constructs inconsistent with each other.
  4. 继续传播“close()”异常,并将try异常注册为suppress,使两个构造彼此不一致。

  5. Just leave everything as it is.
  6. 只要保持原样。

Subjectively I see 3 as less bad than 1 or 2, though it's fairly easy to argue otherwise. I suspect however that this was a dilemma the language developers were faced with and they happened to choose option 3.

主观上我认为3比1或2差,但是否则很容易争论。但我怀疑这是语言开发人员面临的两难选择,他们碰巧选择了选项3。

智能推荐

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.itdaan.com/blog/2015/06/19/72018653b02fc4a4b196cf0ad9218229.html



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告