这是this one的后续问题。
似乎普遍认为,做一个广泛的'捕获(例外)'是一个坏主意。
推理通常类似于“你必须正确处理异常”和“抓住你可以处理的东西”以及其他一些通用的声音参数。
这些通用的答案听起来很合理,但它们并不能让我满意。
让我具体一点。这是典型的代码,应该是“坏”。
try {
... do something...
} catch (Exception e) {
log(e); //leave a trace for debugging
return ...a value the context can deal with...
}
持怀疑态度的人仍然不相信不处理异常(这可能会炸毁整个程序),必然比以这种通用方式处理它更好。
所以我真的想要一些特定的和令人信服的示例,以及代码片段,由于一个像上面那样过于宽泛的catch子句,实际上发生了一些不好的事情。
PS:人们可以用Java以外的其他语言来思考这个问题,但是由于我需要特定的例子,这实际上是关于Java程序和JRE可能引发的特定异常。PS2:我特别感兴趣的是Exception的例子,它实际上是java.lang.Exception的子类型,而不是更广泛的'Throwable'。因此,排除像'OutOfMemoryError'这样的东西作为有效的例子。
答案 0 :(得分:6)
捕获NullPointerException可能会导致应用程序无意中忘记了所需内容尚未完成的事实。稍后应用程序将再次失败或行为异常,因为之前的操作没有完成,但现在更难以弄清楚。
在事务中吃异常可能导致事务本身不会回滚。您最终可能会得到不一致的数据。
吃顿人的异常:
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
doSomeWork();
Thread.sleep();
} catch (Exception e) {
}
}
}
如果线程在休眠时被中断,那么当sleep方法抛出InterruptedException时,中断的标志将被重置,因为catch没有恢复中断标志,while循环条件保持为false并且线程没有出口。
类似地,因为InterruptedIOException是IOException的子类:如果您的网络IO代码只处理IOException,那么您可能无法恢复中断标志并且无法检测到您的线程已被中断。
答案 1 :(得分:0)
原因是您可能希望以不同方式处理不同的异常。
例如,在我编写的某些应用程序中,我需要告知用户确切的错误。如果我只是抓住Exception
,我需要执行额外的检查以区分异常。如果我发现特定的例外,我可以很容易地做不同的事情。
如果我在文件上调用listFiles
,我可能希望在发生SecurityException时显示弹出窗口,但如果发生FileNotFoundException,我可能想要打开FileChooser对话框。
编辑:
既然我在键盘上,我还应该补充一点,有时catch (Exception e)
对于记录有用,但是如果你不打算处理它,那么你应该总是重新抛出那个异常。正如他们所说,一个人的垃圾是另一个人的财富。
答案 2 :(得分:0)
我会转过头来说,我认为只有这样一个过于广泛的捕获才适合的情况是,如果情况是“无论什么在这里失败,我们只是放弃”,如:
try {
/* ... do something terribly important... */
} catch (Exception e) {
System.err.println("We are totally screwed");
e.printStackTrace();
System.exit(1);
}