Java,类特定异常与标准异常的区别

16

我一直在更新一个现有库,以便通过使用该库的人引发异常来帮助改善调试。

起初,我想为每个类定义特定的异常,但是事实证明,这些异常大多只是现有运行时异常的扩展(例如FooNegativeIntArgumentException extends IllegalArgumentExceptionFooNullBarException extends NullPointerException),具有特定的消息。

定义新的异常和使用现有的异常有什么权衡之处?是否有任何惯例或最佳做法?

此外,考虑到向后兼容性的需要,大多数(如果不是全部)这些异常都是运行时异常。


感谢提供了详细解释,说明为什么通常不应使用自定义异常,以及它们实际上有用的情况。 - Carl
6个回答

18
这是我对为什么我们有不同类型的异常以及何时创建自定义异常类型的看法(注意:此处使用.NET类型作为示例,但相同原则适用于使用结构化错误处理的Java和任何其他语言)。这可能太长了,无法在此处发布完整答案,因此我将只发布两个关键摘录。
  1. 何时抛出不同类型的异常?为每个可通过编程方式不同处理的症状抛出不同类型的异常。

  2. 何时创建自定义异常类型?当您需要使用附加信息注释异常以帮助程序处理症状时,请创建自定义异常类型。

在您的情况下,似乎您的自定义异常类型没有填补可以使用标准异常传达的症状差距,并且它们没有添加任何额外的信息以进行程序处理,因此不要创建它们。只需使用标准异常即可。


9
扩展异常而不添加任何价值是完全浪费时间的,会产生不必要的维护成本,最好避免。请使用标准异常。这并不意味着您永远不应该使用自定义异常,只是在您提出的用例中不应使用。此外,在创建自定义异常时,它们应与导致它们的条件相关,而不是可能引发它们的类。将它们与业务/功能区域相关联是可以的,因为导致异常的错误条件很可能是以这种方式相关的,并且它将提供有用的过滤技术。

一如既往...有人比我先回答了。 :-) - cjstehno
只要您从基本异常中扩展,就不会产生客户端成本。在许多情况下,用户定义的异常可以比抛出虚拟异常更明确地处理错误。 - Stefan Kendall
@Stefan - 给出的例子没有任何价值。我不明白为什么针对空指针或错误参数而创建自定义异常会增加任何价值,当然还有维护成本。每个新的参数类型或边界现在都需要一个新的异常,而删除这些类型将留下无用的代码残留。 - Robin

6

来自《Effective Java》

应该优先使用标准异常,并使用Java平台库中的未经检查的异常集合来覆盖您描述的内容。重复使用异常具有以下好处:

使您的API更易于学习和使用,因为它符合程序员已经熟悉的既定约定

较少的异常类意味着更小的内存占用和更少的加载类所需的时间。


链接已失效。 http://www.oracle.com/technetwork/java/effective-exceptions-092345.html 这是吗?还是链接只是关于如何购买该书的信息? - Raystorm

2

一个调用者需要捕获FooNegativeIntArgumentException而不是IllegalArgumentException的可能性有多大?

我的猜测是几乎从不会发生,因此在出现需要区分的情况之前,我会坚持使用基本异常。


1

权衡?很多工作,很多代码需要维护,而且时间就是金钱。我建议:只有在需要它们来过滤日志、进行精细异常处理或调试(为特殊异常类型设置断点)时才定义新的异常。


1
我会使用明确定义的异常来给客户端代码更多的控制权。如果客户端想要,他们可以像你上面的例子一样捕获 IllegalArgumentException 异常。如果他们需要更多的控制,他们可以捕获单个类型的异常。例如,考虑一个可能抛出两个 IllegalArgumentException 子类的方法。如果你不使用子类,你必须进行字符串解析或其他一些无聊的操作来确定抛出异常的实际原因。用户定义的类型可以解决这个问题。

我认为这种方法的成本效益比重更倾向于成本方面。 - Robin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接