未检查异常

因为Java编程语言不需要捕获方法或声明未检查异常(包括 RuntimeException、Error及其子类),程序员可能会试图编写只抛出未检查异常的代码,或使所有异常子类继承自RuntimeException。这两个快捷方式都允许程序员编写代码,而不必担心编译器错误,也不用担心声明或捕获任何异常。虽然这对于程序员似乎很方便,但它避开了捕获或者声明异常的需求,并且可能会导致其他人在使用您的类而产生问题。

为什么设计人员决定强制一个方法来指定所有可以抛出的未捕获的已检查异常?任何可以由方法抛出的 Exception 都是方法的公共编程接口的一部分。调用方法的人必须知道一个方法可以抛出的异常,以便他们可以决定如何处理它们。这些异常是该方法的编程接口的一部分,作为它的参数和 return 值。

下一个问题可能是:“既然一个方法的API已经做好了很好的记录,包括它可以抛出的异常,为什么不指定运行时异常?”运行时异常展示的是编程问题的结果,因此,API用户可能会用不合理方式来处理它们。这样就有可能产生问题,包括算术异常,例如除以零;指针异常,例如试图通过空引用访问对象;索引异常,例如尝试通过太大或太小的索引访问数组元素。

运行时异常可能发生在程序中的任何地方,在典型的程序中它们可以非常多。必须在每个方法声明中添加运行时异常则会降低程序的清晰度。因此,编译器不需要捕获或声明运行时异常(尽管可以是可以做到)。

一种情况是,通常的做法是当用户调用一个方法不正确时,抛出一个RuntimeException。例如,一个方法可以检查其中一个参数是否不正确为null。如果参数为null,那么该方法可能会抛出NullPointerException异常,这是一个未检查异常。

一般来说,不要抛出一个RuntimeException或创建一个RuntimeException的子类,这样你就不会被声明哪些方法可以抛出的异常所困扰。

一个底线原则是:如果客户端可以合理地从期望异常中恢复,那么使其成为一个已检查异常。如果客户端无法从异常中恢复,请将其设置为未检查异常。