资源关闭的例外最终隐藏了另一个 - 谁在乎呢?

时间:2012-10-02 20:47:39

标签: java exception-handling java-io

首先,很抱歉提出一个关于什么是一个陈旧的主题的问题。我遇到了很多问题,答案暗示从关闭finally块中的资源的方法中吞下(捕获并忽略/记录)潜在异常。这似乎是一种普遍接受的模式。但我还没有看到任何人解释为什么。这只是一个例子:Try-catch-finally and then again a try catch

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

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

我目前的理解是:

  1. 如果只有close抛出异常,我们绝对不想吞下它。
  2. 如果useclose都抛出异常,那可能是出于同样的潜在原因,并且哪个异常传播起来并不重要(它们都包含同样有用的信息?)。
  3. 如果otherclose都抛出异常,则会出现两个不相关的问题。可以说,首先发生的那个应该传播,但没有任何理由建议第一个例外导致第二个(是吗?),所以要么会这样做。
  4. 我错了什么?

1 个答案:

答案 0 :(得分:3)

  

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

没错!

  

如果同时使用和关闭抛出异常,它可能是出于同样的潜在原因,并且哪个异常传播起来并不重要(它们都包含同样有用的信息?)。

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

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

  

如果其他和close抛出异常,则存在两个无关的问题。 [...]没有任何理由建议第一个例外导致第二个(是吗?),所以要么会这样做。

实际上,两个例外都是导入,但第一个例外可能更相关。解?在Java 7和try-with-resources idiom中使用AutoCloseable资源。如果在清理时发生异常,它将作为压缩

附加到原始异常
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)
        }