首先,很抱歉提出一个关于什么是一个陈旧的主题的问题。我遇到了很多问题,答案暗示从关闭finally块中的资源的方法中吞下(捕获并忽略/记录)潜在异常。这似乎是一种普遍接受的模式。但我还没有看到任何人解释为什么。这只是一个例子:Try-catch-finally and then again a try catch。
我理解从finally块抛出的任何异常都会“掩盖”相应try块中抛出的任何异常,但我不明白为什么这是一件坏事。例如:
Resource r = new Resource();
try {
r.use();
other();
} finally {
r.close();
}
我目前的理解是:
close
抛出异常,我们绝对不想吞下它。use
和close
都抛出异常,那可能是出于同样的潜在原因,并且哪个异常传播起来并不重要(它们都包含同样有用的信息?)。 other
和close
都抛出异常,则会出现两个不相关的问题。可以说,首先发生的那个应该传播,但没有任何理由建议第一个例外导致第二个(是吗?),所以要么会这样做。我错了什么?
答案 0 :(得分:3)
如果只关闭抛出异常,我们绝对不想吞下它。
没错!
如果同时使用和关闭抛出异常,它可能是出于同样的潜在原因,并且哪个异常传播起来并不重要(它们都包含同样有用的信息?)。
不是真的。 try
中的例外情况可能是NullPointerException
,OutOfMemoryError
或描述问题性质的实际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)
}