因为Java编程语言不强制要求方法去捕获或声明非检查异常(RuntimeException,Error和它们的子类),程序员可能会只编写那种只抛出非检查异常的代码,或者让他们自己定义的异常全部继承于RuntimeException。这些短视的做法都可以让程序员写出不受编译期错误打扰的代码,而且不用声明或捕获任何异常。尽管对于程序员来说很方便,它回避了捕获或声明的强制要求,但是却会给程序的使用者造成麻烦。

为什么设计者决定强制要求一个方法一定要声明那些在方法范围内可能会抛出的未被捕获的检查异常?方法中任何可能抛出的异常,都是这个方法的公开编程接口的一部分。调用方法的人必须要知道这个方法可能会抛出什么异常,进而可以决定怎么处理它们。异常是方法的公开编程接口的一部分,就跟方法的参数和返回值一样。

下一个问题可能就是:“既然方法中包含可能会抛出的异常那么好,让方法的API可以更加文档化,那为什么不把运行时异常也一起声明了?”运行时异常代表了由于编码问题带来的问题,所以,API的客户端代码不能合理地恢复或处理它们。这样的异常包括算术异常,比如除数为0;指针异常,比如通过一个空引用访问对象;还有索引异常,比如通过一个过大或过小的索引访问一个数组。

运行时异常可能发生在程序的任何地方,而且种类繁多。把运行时异常加在每一个方法的声明从句里面,会让代码变得不清晰。所以,编译期并不要求你抛出或捕获运行时异常(当然你想这么做也行)。

一个很常见的实践就是,当用户调用一个方法的方式不正确时,这个方法就抛出运行时异常。例如,一个方法可以检查它的其中一个参数是否错误地传入了null。如果一个参数是null,这个方法可能会抛出NullPointerException(一种非检查异常)。

一般来说,如果只是因为你不想被一大串的方法声明所烦扰,不要因此抛出运行时异常或者创建RuntimeException的子类。

这是最基本的指导原则:如果客户端可以合理地预期从一个异常中恢复,就让这个异常是检查异常。如果客户端不能从一个异常中恢复做任何事,就让这个异常是非检查异常。





原文地址