gpt4 book ai didi

java - 使用finally时抑制的异常消失了?

转载 作者:行者123 更新时间:2023-11-30 07:03:28 24 4
gpt4 key购买 nike

这是代码。

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 block 抛出的异常抑制了资源中的异常,因此我首先得到“抑制的异常:1”,这是可以理解的。但是当从finally抛出异常时,似乎所有抑制的异常都消失了,因为我得到了“java.lang.Exception:finally的异常”,后面跟着“抑制的异常:0”,我认为它应该是1 。我浏览了 Java 教程,它肯定说

However, in this example, if the methods readLine and close both throw exceptions, then the method readFirstLineFromFileWithFinallyBlock throws the exception thrown from the finally block; the exception thrown from the try block is suppressed.

来自The try-with-resources Statement

怎么会发生这种事?

最佳答案

下面的代码可以实现您所期望的功能:

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 部分(如 JDK 1.7.0 中所介绍),看看会发生什么(有关更多详细信息,请参阅 What is the Java 7 try-with-resources bytecode equivalent using try-catch-finally?):

  • 执行 try-with-resource block MyResource r = new MyResource("resource")
  • try block 被执行并抛出 IllegalArgumentException
  • try-with-resource block 为所有资源调用 close()(在您的示例中只有一个)
  • close() 抛出异常,但由于 try block 中的异常具有优先级,因此 close() 引发的异常会被抑制并通过 添加addSuppressed(..)

因此,该部分的工作原理与您阅读本教程时所期望的一样。

现在代码的 try-catch-finally 部分(如 JDK 1.6 及更早版本):

  • try block 被执行并抛出 IllegalArgumentException
  • (catch block 的行为与没有 catch block 的行为相同)
  • finally block 被执行并抛出异常
  • finally block 中的异常优先,try block 中的异常被抑制

但是这次java教程中使用的单词抑制并不代表“抑制并添加到实际抛出的异常中”而是“被压抑并迷失于涅槃”。因此,它的行为仍然与 JDK 1.6 及更早版本中相同,并且不使用新引入的 addSuppressed(..) getSuppressed() 功能。这就是它的行为与您预期不同的原因。

<小时/>

我认为您所期望的行为也不符合逻辑。我希望它的行为像这样:

...
} finally {
try {
new MyResource("finally").close();
} catch (Exception e) {
if (exceptionFromCatch!=null) {
exceptionFromCatch.addSuppressed(e);
} else {
throw e;
}
}
}
...

这将始终优先考虑来自 try block 的异常(通过新的 try-with-resource 功能实现),并将来自 catch block 的异常添加为被抑制到列表中。但这会破坏与 JDK 1.6 的兼容性,所以我想这就是它不这样做的原因。

关于java - 使用finally时抑制的异常消失了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40503733/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com