需要权威的来源,为什么你不应该抛出或捕获java.lang.Exception

时间:2009-10-16 14:52:37

标签: java exception-handling

我在短短一个多小时内就完成了编码标准会议,我需要快速回答这个问题。

有经验的Java程序员之间的共同点是,你不会抛出或捕获java.lang.Exception(极少数例外 - 没有双关语)。你不这样做的原因是声明

catch (java.lang.Exception ex) {...}

也会捕获未经检查的异常,在大多数情况下,这不是预期的。

我们已经有很多遗留代码由现有团队成员编写,他们捕获java.lang.Exception的子类,记录错误,并将子类重新抛出为java.lang.Exception。

我需要说服他们

  1. 他们需要停止编写这样的代码。
  2. 需要修复使用此反模式的现有代码
  3. 2号意味着相当多的重构。

    如果我可以向一位提出这一点的Java社区重量级人物展示一篇文章或博客文章(即Joshua Bloch,James Gosling),它将缩短会议上的论点。到目前为止,我的google-fu还没有找到任何东西。

    有没有人知道一位受人尊敬的Java专家的文章或博客,说你不应该抛出或捕获java.lang.Exception?

    非常感谢快速回答。

    迪安

9 个答案:

答案 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)

这里没有共同点。你会发现两组:

  1. 那些讨厌检查异常的人会抓住并用某种RuntimeException包裹它们。

  2. 讨厌RuntimeException

  3. 的人

    第一组讨厌用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. 对意外情况使用未经检查的例外(例如:数据库服务器已关闭)
  3. 理论上,#1(预期错误)应该有自己的异常类型,唯一应该捕获#2(RuntimeException)的地方是某种类型的顶级处理程序,它捕获异常,记录它,以及向用户显示错误消息,即使在这里,您也应该捕获Throwable以确保处理任何未捕获的异常。

    遵循这些准则,您不应该捕获Exception,因为它不符合上述任何一个条件(意思是,它不是RuntimeException,并且它不是指示预期错误的专门Exception sublcass。)

答案 6 :(得分:1)

这是一个非常insightful article

摘要:

  1. 对于与代码目的相关的罕见但有效的意外情况,请使用已检查的例外情况。客户端代码应该知道如何处理这些。

  2. 对不应发生但不会发生的故障使用未经检查的例外。 (服务器关闭,类路径配置错误,SQL语法错误等)管理服务器的IT人员或刚刚将错误的SQL传递给prepareStatement()的开发人员应该知道如何解决这些问题。故障应传播到日志记录层,以便信息不会丢失。

答案 7 :(得分:0)

我想重点是,如果你不知道如何处理特定的异常,那么你就不应该抓住它。它应该传播到更高的层次,希望它可能知道如何处理它。过早捕捉异常导致异常被静默吞噬,并且除了记录之外不可能对它们做任何有用的事情。

想象一下,如果FileInputStream的构造函数在内部记录异常,如果您尝试打开一个不存在的文件,但未向您的代码指出此失败,会发生什么。可以记录错误,但是您的代码希望捕获此异常并对其执行一些有用的操作(例如提示用户输入新文件名)。如果他们是catch (Exception)你将无法做到这一点。

答案 8 :(得分:0)

如果你有一份Josh Bloch的Effective Java副本,我知道他会在那里详细介绍异常处理。我目前无法访问它,所以我不能总结它或给你页面引用,但我很确定他有一些很好的论据,因为没有捕获java.lang.Exception。

相关问题