使用以下代码:
try {
throw new RuntimeException ("main");
}
finally {
throw new RuntimeException ("finally");
}
我得到了这个结果:
Exception in thread "main" java.lang.RuntimeException: finally
at test.main(test.java:12)
但是,通过在Java 7中添加抑制的异常,当finally
块本身因异常而失败时,语言将原始“主”异常注册为抑制是不合逻辑的?目前我必须手动模拟这个:
try {
throw new RuntimeException ("main");
}
catch (RuntimeException exception) {
try {
throw new RuntimeException ("finally");
}
catch (RuntimeException exception2) {
exception2.addSuppressed (exception);
throw exception2;
}
}
获得更多有用的(用于了解正在发生的事情)结果:
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)
编辑:澄清我在想什么。目前的Java版本是8,抑制异常不是一个全新的功能。但是try..finally
仍然没有包含它们。是否存在阻止这种情况发生的事情?
答案 0 :(得分:8)
因为try-with-resources是语法糖,Java编译器不会以相同的方式扩展常规的try-finally块。
看看以下代码:
try(FileInputStream fstream = new FileInputStream("test")) {
fstream.read();
}
编译然后反编译(使用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();
}
}
}
这段代码:
FileInputStream fstream = new FileInputStream("test");
try {
fstream.read();
} finally {
fstream.close();
}
在编译和反编译时看起来完全相同。
现在,可以肯定的是,所有finally
块都应该以与上面相同的方式进行扩展,但由于某些原因而被忽略或决定反对。
我建议你open a feature request,因为我认为这是一个明智的功能。
答案 1 :(得分:5)
这不是一个权威的答案,但看起来这样的更改会破坏兼容性,或者try-with-resources
和try-finally
会相互矛盾。
try-with-resources
中的语义是传播try
块引发的异常,并在调用注册为suppress的close()
方法时抛出异常。从实际的角度来看,这是有道理的,你想要抓住你的“真实”异常,然后如果你愿意,也可以处理未关闭的资源。
但在try-finally
中,finally
中传播的异常是传播的(而try
中的一个被“吞噬”),因此我们可以选择三种不良解决方案:
try-finally
的逻辑,使其与try-with-resources
对齐并破坏代码(或更确切地说,错误)与之前所有代码的兼容性。close()
”异常,并将try
异常注册为已抑制,使两个构造彼此不一致。主观上我认为3比1或2差,但是否则很容易争论。但我怀疑这是语言开发人员面临的两难选择,他们碰巧选择了选项3。