在方法签名中应该指明抛出RuntimeException吗?

103

例如,许多框架/JDK中的方法可能会抛出

java.lang.SecurityException 

但是在方法签名中没有指明这一点(因为这通常是为已检查的异常保留的做法)。 我想争论声明RuntimeExceptions在方法签名中有许多好处(类似于静态类型检查)。 我是醉了还是其他的原因?

7个回答

81

在签名中声明未经检查的异常是误导 API 用户的行为,因此我不会这样做。现在不再明显该异常是否必须显式处理。

在 javadoc 中声明它是一种更好的方法,因为它允许某些人在认为必要时处理它,但也知道他们可以忽略它,从而清晰地区分已检查和未检查的异常。


7
Java编译器不强制您处理已声明的RuntimeException。因此,您可以声明它们,作为对开发人员的“提示”。关于这点,是否应该将其放在JavaDoc中进行讨论。检查异常和未检查异常非常重要。检查异常和未检查异常是Java真正意义上的(编译时)异常(检查的)和RuntimeException(未检查的)。 - Guardian667
7
在春季,将未经检查的异常声明在方法签名中成为一种常见做法。 - johnlemon

46

来自Oracle Java教程

"如果记录一个方法的API(应用程序编程接口)包括它可能抛出的异常是如此重要,为什么不指定运行时异常呢?" 运行时异常代表的是由于编程问题而产生的问题,因此,API客户端代码不能合理地预期从中恢复或以任何方式处理它们。这些问题包括算术异常,例如除以零;指针异常,例如尝试通过null引用访问对象;和索引异常,例如尝试通过太大或太小的索引访问数组元素。

运行时异常可以在程序的任何位置发生,并且在典型的程序中可能非常多。 在每个方法声明中添加运行时异常将降低程序的清晰度。


因此,编译器不要求您捕获或指定运行时异常(尽管您可以这样做)。 - johnlemon

20

请查看Collection#add的javadoc文档。

文档中提到了一系列未经检查的异常:

Throws:
UnsupportedOperationException - add is not supported by this collection.
ClassCastException - class of the specified element prevents it from being added to this collection.
NullPointerException - if the specified element is null and this collection does not support null elements.
IllegalArgumentException - some aspect of this element prevents it from being added to this collection.

如果你有耐心,我建议你这样彻底记录方法可能抛出的异常。在某种程度上,对于未经检查的异常更加重要,因为已检查的异常有些是自注释的(编译器强制调用代码承认它们)。


9
这个答案是错误的。你谈论的是Javadoc语句,而问题是关于方法签名中的throws关键字。这不是同一件事情。是的,你绝对应该记录API抛出的所有异常,但问题不是关于那个的。 - Gili

6

在我看来,至少应该在方法的javadoc中声明运行时异常。在签名中声明它会更加明显,在出现问题时可能发生什么。这是我建议提供此信息的主要原因。

顺便说一下,随着时间的推移(现在是2017年),我现在更倾向于仅在javadoc中记录它们,并尽可能避免使用受检异常。


应该避免未检查的异常而不是“避免已检查的异常”吗? - Szymon Roziewski
1
不行,因为受检异常很麻烦。它强制你处理或声明它们。有时你不能这样做(lambda表达式!),那么你就必须将其包装在运行时异常中。所以最好声明它们,让程序员决定哪些地方需要处理,哪些应该传播到顶层。 - Patrick Cornelissen

3

在我看来,未经检查的异常不应该在方法签名中声明,因为这与它们的本质相反。

然而,如果一个方法可能会抛出一些未经检查的异常,在 Javadoc 的 @throws 中注明可能的情况,对于调用该方法的其他人理解可能出现的问题是有帮助的。但是,这仅对调用者可能能够处理的异常有用(例如由于错误输入导致的 NPE 等)。


3

如果您正在编写供他人使用的 API,则有充分的理由在 API 中明确记录您的意图,并且在方法签名中声明 RuntimeExceptions 没有任何不利影响。


1
这与讨论检查异常有关。大多数人都认为,异常不应在方法签名中声明。

还有讨论有关如何使用运行时异常。我同意一个帖子的观点,即运行时异常应该表示编程错误或致命条件。因此,在签名中声明它们并没有太大的价值。每个方法都可能抛出一个。


那么解析异常或其他数据验证类型的异常应该放在哪里呢?您暗示不应使用已检查的异常,但又限制了未检查的异常的使用范围。 - Robin
1
我想说的是开发人员不应被强制捕获已检查异常。因此,在方法签名中没有必要声明它们。在Java中,可以将它们转换为运行时异常,就像Spring正在做的那样。我还想说,仅应在不可恢复的情况下抛出运行时异常。 - kgiannakakis

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