我在短短一个多小时内就完成了编码标准会议,我需要快速回答这个问题。
有经验的Java程序员之间的共同点是,你不会抛出或捕获java.lang.Exception(极少数例外 - 没有双关语)。你不这样做的原因是声明
catch (java.lang.Exception ex) {...}
也会捕获未经检查的异常,在大多数情况下,这不是预期的。
我们已经有很多遗留代码由现有团队成员编写,他们捕获java.lang.Exception的子类,记录错误,并将子类重新抛出为java.lang.Exception。
我需要说服他们
2号意味着相当多的重构。
如果我可以向一位提出这一点的Java社区重量级人物展示一篇文章或博客文章(即Joshua Bloch,James Gosling),它将缩短会议上的论点。到目前为止,我的google-fu还没有找到任何东西。
有没有人知道一位受人尊敬的Java专家的文章或博客,说你不应该抛出或捕获java.lang.Exception?
非常感谢快速回答。
迪安
答案 0 :(得分:6)
这是:Java Tip 134: When catching exceptions, don't cast your net too wide(JavaWorld)
Joshua Bloch的 Effective Java(第二版)可能在第9章(例外)中有一些内容,尽管我无法快速找到关于不捕捉Exception
的任何内容。
以下是a Q&A from JavaWorld关于这个问题(也指向Java技巧134) - 它还解释了为什么有时你必须违反不捕捉Exception
甚至Throwable
的规则。< / p>
答案 1 :(得分:5)
请参阅Brian Goetz的this article(并发向导),他有自己的洞察力,并在Effective Java中引用Josh Bloch
答案 2 :(得分:4)
这里没有共同点。你会发现两组:
那些讨厌检查异常的人会抓住并用某种RuntimeException
包裹它们。
讨厌RuntimeException
第一组讨厌用try...catch
来捣乱他们的代码,特别是因为在大多数情况下,当你第一次看到它时你无法处理异常。想想IOException
:可能会为您读取的每个字节抛出。什么是低级代码呢?它必须重新抛出它,以便更高级别的人可以为错误添加一些有用的上下文(比如你正在阅读的文件)。
另一组希望看到可能出现的问题。 RuntimeException
有效地隐藏了这一点。
有一个简单的修复,BTW:Make Exception扩展RuntimException。疯?并不是的。如果使用JDK 7执行此操作,则会出现两个编译错误。
下一步是让所有Java编译器枚举所有运行时异常并将它们列在类文件的throws
条目中。你仍然不必抓住它们,但现在,你会知道哪些可能发生。
最后,扩展IDE以显示它。而且,两个团体都很开心。不幸的是,这不会发生。
答案 3 :(得分:3)
这是Bruce Eckel's viewpoint on checked exceptions in general,在大多数情况下,这是一个坏主意。也许那会有你可以使用的东西。
答案 4 :(得分:2)
他们捕获java.lang.Exception的子类,记录错误,并将子类重新抛出为java.lang.Exception。我需要说服他们,他们需要停止编写这样的代码。
我同意他们应该使用另一种策略,但出于不同的原因。捕获异常只是为了记录它并重新抛出它没有多大意义。
另一种方法是:不要捕获异常并让一些更高级的代码(如Java EE Filter,或者main()方法中的try / catch)捕获并记录所有未捕获的异常。然后确保每个异常只记录一次,并且您知道将记录所有未捕获的异常。
如果您需要向异常添加额外信息,请捕获它,更改消息并重新抛出它。我通常使用RuntimeException:
} catch (Exception originalException) {
throw new RuntimeException("user name was " + userName, originalException);
}
答案 5 :(得分:1)
这是一篇很长的文章,但this建议你:
理论上,#1(预期错误)应该有自己的异常类型,唯一应该捕获#2(RuntimeException)的地方是某种类型的顶级处理程序,它捕获异常,记录它,以及向用户显示错误消息,即使在这里,您也应该捕获Throwable以确保处理任何未捕获的异常。
遵循这些准则,您不应该捕获Exception,因为它不符合上述任何一个条件(意思是,它不是RuntimeException,并且它不是指示预期错误的专门Exception sublcass。)
答案 6 :(得分:1)
这是一个非常insightful article
摘要:
对于与代码目的相关的罕见但有效的意外情况,请使用已检查的例外情况。客户端代码应该知道如何处理这些。
对不应发生但不会发生的故障使用未经检查的例外。 (服务器关闭,类路径配置错误,SQL语法错误等)管理服务器的IT人员或刚刚将错误的SQL传递给prepareStatement()的开发人员应该知道如何解决这些问题。故障应传播到日志记录层,以便信息不会丢失。
答案 7 :(得分:0)
我想重点是,如果你不知道如何处理特定的异常,那么你就不应该抓住它。它应该传播到更高的层次,希望它可能知道如何处理它。过早捕捉异常导致异常被静默吞噬,并且除了记录之外不可能对它们做任何有用的事情。
想象一下,如果FileInputStream
的构造函数在内部记录异常,如果您尝试打开一个不存在的文件,但未向您的代码指出此失败,会发生什么。可以记录错误,但是您的代码希望捕获此异常并对其执行一些有用的操作(例如提示用户输入新文件名)。如果他们是catch (Exception)
你将无法做到这一点。
答案 8 :(得分:0)
如果你有一份Josh Bloch的Effective Java副本,我知道他会在那里详细介绍异常处理。我目前无法访问它,所以我不能总结它或给你页面引用,但我很确定他有一些很好的论据,因为没有捕获java.lang.Exception。