4

首先,很抱歉问了一个关于什么是老生常谈的话题的问题。我遇到了很多问题,答案建议从关闭 finally 块中的资源的方法中吞下(捕获和忽略/记录)潜在异常。这似乎是一种普遍接受的模式。但是我还没有看到有人解释原因。这里只是一个例子:Try-catch-finally 和 try catch

我知道从 finally 块抛出的任何异常都会“掩盖”在相应的 try 块中抛出的任何异常,但我不明白为什么这是一件坏事。例如:

Resource r = new Resource();
try {
    r.use();
    other();
} finally {
    r.close();
}

我目前的理解是:

  1. 如果只是close抛出一个异常,我们绝对不想吞下它。
  2. 如果两者都use抛出close异常,则可能是出于相同的根本原因,并且传播哪个异常并不重要(它们都将包含同样有用的信息?)。
  3. 如果两者都other抛出close异常,则有两个不相关的问题。可以说,首先发生的那个应该传播,但是没有任何理由表明第一个异常导致了第二个异常(存在吗?),所以两者都可以。

我错了什么?

4

1 回答 1

3

如果只是 close 抛出异常,我们绝对不想吞下它。

这是正确的!

如果 use 和 close 都抛出异常,则可能是出于相同的根本原因,并且传播哪个异常并不重要(它们都将包含同样有用的信息?)。

并不真地。中的异常try可能是NullPointerExceptionOutOfMemoryError描述问题性质的实际 I/O 异常。即使是 I/O 异常,错误也可能使流处于不一致状态(甚至过早关闭)。调用close()可能会产生完全不同的错误,例如“流已关闭”、“内部错误”等。

系统中的一个错误往往会引发数十个其他错误,有时看起来非常不相关。始终寻找根本原因的第一个异常。其余的只是垃圾。一个很好的例子是初始化失败并使对象处于不一致状态。后来你到处都能看到NullPointerExceptions,但真正的问题发生得更早。

如果 other 和 close 都抛出异常,则有两个不相关的问题。[...] 没有任何理由表明第一个异常导致了第二个异常(存在吗?),所以两者都可以。

实际上,这两个例外都是进口,但第一个可能更相关。解决方案?AutoCloseable在 Java 7 和try-with-resources idiom 中使用资源。如果清理时发生异常,它将附加到原始异常作为抑制

class Resource implements AutoCloseable  //...

接着:

try(Resource r = new Resource()) {
    r.use();
    other();
}

异常将如下所示:

MyException: Exception in use()
at Resource.use(Main.java:11)
at Main.main(Main.java:16)
    Suppressed: java.lang.RuntimeException: Exception in close()
        at Main.close(Main.java:6)
        at Main.main(Main.java:17)
        }
于 2012-10-02T20:53:18.100 回答