Java 最终使用时抑制的异常消失?
这是密码Java 最终使用时抑制的异常消失?,java,exception,try-with-resources,Java,Exception,Try With Resources,这是密码 public class TestTest { public static void main (String[] args) throws Exception { try { run(); } catch(Exception e) { printSuppressedExceptions(e); } } public static void printSuppres
public class TestTest {
public static void main (String[] args) throws Exception {
try {
run();
} catch(Exception e) {
printSuppressedExceptions(e);
}
}
public static void printSuppressedExceptions(Throwable t) {
System.out.println(t);
System.out.println("suppressed exceptions: " + t.getSuppressed().length);
}
public static void run() throws Exception {
try(MyResource r = new MyResource("resource");) {
System.out.println("try");
System.getProperty("").length(); // throws illegalArgumentException
} catch(Exception e) {
printSuppressedExceptions(e);
throw e;
} finally {
new MyResource("finally").close();
}
}
}
class MyResource implements AutoCloseable {
private final String name;
public MyResource(String name) {
this.name = name;
}
@Override
public void close() throws Exception {
throw new Exception("exception" + " from " + this.name);
}
}
因为从try块抛出的异常抑制了来自资源的异常,所以我首先得到了“抑制的异常:1”,这是可以理解的。但是当一个异常从finally抛出时,似乎所有被抑制的异常都消失了,因为我得到了“java.lang.exception:exception from finally”,然后是“被抑制的异常:0”,我认为它应该是1。
我浏览了Java教程,它明确地说
但是,在本例中,如果readLine和close方法都抛出异常,那么readFirstLineFromFileWithFinallyBlock方法抛出finallyblock块抛出的异常;从try块引发的异常被抑制
从
它是如何发生的?以下是实现您期望的功能的代码:
public class TestTest {
public static void main (String[] args) throws Exception {
try {
run();
} catch(Exception e) {
printSuppressedExceptions(e);
}
}
public static void printSuppressedExceptions(Throwable t) {
System.out.println(t);
System.out.println("suppressed exceptions (" + t.getSuppressed().length + "):");
for (Throwable suppressed : t.getSuppressed()) {
System.out.println(" - " + suppressed);
}
}
public static void run() throws Exception {
Exception exceptionFromCatch = null;
try(MyResource r = new MyResource("resource");) {
System.out.println("try");
System.getProperty("").length(); // throws illegalArgumentException
} catch(Exception e) {
exceptionFromCatch = e;
printSuppressedExceptions(e);
throw e;
} finally {
try {
new MyResource("finally").close();
} catch (Exception e) {
if (exceptionFromCatch!=null) {
e.addSuppressed(exceptionFromCatch);
}
throw e;
}
}
}
}
class MyResource implements AutoCloseable {
private final String name;
public MyResource(String name) {
this.name = name;
}
@Override
public void close() throws Exception {
throw new Exception("exception" + " from " + this.name);
}
}
因此,让我们来看看代码的try-with-resource部分(如JDK1.7.0中介绍的),看看会发生什么(有关更多详细信息,请参阅):
- 执行try with resource块
MyResource r=newmyresource(“资源”)
- 执行try块并抛出一个
IllegalArgumentException
- try with resource块调用所有资源的
(在您的示例中仅一个)close()
引发异常,但由于try块中的异常具有优先级,因此close()
引发的异常被抑制,并通过close()
addsupprested(..)添加。
- 执行try块并抛出一个
IllegalArgumentException
- (捕捉块的行为方式与没有捕捉块时相同)
- 执行finally块并抛出异常
- 来自finally块的异常具有优先级,而来自try块的异常被抑制
addsupprested(..)
getsupprested()
功能。这就是为什么它不像你期望的那样
我认为你所期望的行为也不符合逻辑。我希望它表现得像这样:
...
} finally {
try {
new MyResource("finally").close();
} catch (Exception e) {
if (exceptionFromCatch!=null) {
exceptionFromCatch.addSuppressed(e);
} else {
throw e;
}
}
}
...
这将始终优先考虑try块中的异常(使用新的try with resource功能实现),并将catch块中的异常添加到列表中。但是这会破坏与JDK1.6的兼容性,所以我想这就是它不这样做的原因。只是猜测:可能是这样,因为抛出了两个异常?当try with resources关闭r时,我期望从
r.close()
中得到一个,从finally块中创建并关闭的附加对象中得到另一个……此外,引用的文本引用了先前Java 7使用try{read()}finally{close()}
的示例。我建议你读整段,然后继续读“抑制例外”一段。谢谢。我想@tuempl刚刚解决了我的困惑。但是这次java教程中使用的单词supprested并不是“supprested并添加到实际抛出的异常”而是“supprested and lost to nirvana”。啊哈,我想所有被抑制的异常都会添加到实际抛出的异常中,从1.7开始,这是完全错误的。