未经检查的 exceptions-争议

因为 Java 编程语言不需要catch或指定未经检查的异常(RuntimeExceptionError及其子类)的方法,所以程序员可能会倾向于编写仅引发未经检查的异常的代码或使它们的所有异常子类继承自RuntimeException。这两种快捷方式均允许程序员编写代码,而不必担心编译器错误,也不必费心指定或catch任何异常。尽管这对于程序员来说似乎很方便,但它回避了catchspecify要求的意图,并可能给其他使用您的类的人带来麻烦。

设计者为什么决定强制使用一种方法来指定可以在其范围内引发的所有未catch的检查异常?方法可以抛出的任何Exception都是该方法的公共编程interface的一部分。那些调用方法的人必须了解方法可能引发的异常,以便他们可以决定如何处理这些异常。这些异常与该方法的参数和return值一样,也是该方法的编程interface的一部分。

下一个问题可能是:“如果很好地记录一个方法的 API,包括它可以抛出的异常,为什么不还要指定运行时异常呢?”运行时异常表示由编程问题引起的问题,因此,无法合理地期望 APIClient 端代码从它们中恢复或以任何方式进行处理。这些问题包括算术异常,例如被零除;指针异常,例如try通过空引用访问对象;以及索引异常,例如try通过太大或太小的索引访问数组元素。

运行时异常可能在程序中的任何地方发生,在典型情况下,异常可能非常多。必须在每个方法声明中添加运行时异常会降低程序的清晰度。因此,编译器不需要catch或指定运行时异常(尽管可以)。

通常的做法是,当用户错误地调用方法时,抛出RuntimeException。例如,一个方法可以检查其参数之一是否错误null。如果参数是null,则该方法可能会抛出NullPointerException,这是一个* unchecked *异常。

一般来说,不要仅仅因为您不想指定方法可能抛出的异常而抛出RuntimeException或创建RuntimeException的子类。

这是最基本的准则:如果可以合理地预期 Client 端将从异常中恢复,则将其设置为已检查的异常。如果 Client 端无法采取任何措施来从异常中恢复,请将其设置为未经检查的异常。