Effective Java(2nd Edition) Item 58 受检查异常用作可恢复条件,运行时异常用作程序错误

Java语言提供了三种异常:受检查异常、运行时异常与错误。有些程序员会迷惑何时使用哪种异常更为合适。虽然选择不总是清晰明了,但仍有些一般规则可用作指南。

       使用受检查异常还是未受检查异常的最主要规则是:受检查异常用作这些情况,即调用者有望在异常情况下合理的恢复程序运行。抛出受检查异常就迫使调用者在catch语句中捕获异常或向上传播。因此,方法声明中所抛出的每个受检查异常对API的使用者就可能暗示着:方法调用的结果与某些条件关联。

       API用户面对受检查异常,API设计者表明了能从异常情形中恢复程序运行的意愿。用户可以通过捕获异常或忽略异常而对这种意愿置之不理,但通常这是有害的想法。

       有两类未受检查异常:运行时异常与错误。它们的行为是一样的,即所抛出的异常不需要,一般也不应该被捕获。如果程序抛出了未受检查异常或错误,通常是不可恢复的情形,程序继续运行有害无益。如果程序没有捕获这样的异常,异常就会使当前线程停止运行,并显示适当的错误信息。

       请使用运行期异常表明程序错误。大部分运行期异常表明前置条件背离。背离前置条件就是API客户破坏了本该遵守的API规范所确定的契约。例如,对数组访问的契约就规定了数组索引值应在0与数组长度减一之间。ArrayIndexOutOfBoundsException表明了这个前置条件被破坏。

       虽然Java语言规范没有要求,但对Error有这样一种广为认同的惯用法:错误保留由JVM使用,用来表明资源缺乏、不变量失败,或其它程序不可能再继续运行的情况。由于该惯用法已被广为接收,因此最好不要实现Error类的任何子类。总之,所有未受检查的异常应实现为RuntimeExceptio的子类(直接或间接的)。

       可定义一个异常,它不是ExceptionRuntimeExceptionError的子类。JLS对此没有明确说明,但暗示其行为与普通的受检查异常的行为相同(是Exception的子类但不是RuntimeException的子类)。哪你何时使用这样一个怪物呢?一言以蔽之,从不。对一个一般的受检查异常这样做没有任何好处,反而会引起API的使用者的混乱。

       总而言之,对可恢复条件用受检查异常,对程序错误用未受检查异常。当然,也不总是非此即彼。例如,考虑资源耗尽的情形,这可能是因为程序中分配了不合理的大数组这样的错误而引起的,也可能是资源确实不足而引起。如果资源耗尽是由于临时不足或临时高强度需求所致,这种情形或许就可以恢复。资源耗尽这样一个具体实例是否允许被恢复,就成了API设计者的一个判断了。如果你认为可恢复,你就用受检查异常,如果你认为不可恢复,你就用运行时异常。如果你不太确信是否可恢复,哪最好还是用未受检查异常,理由在Item 59中讨论。

       API的设计者常常忘记了异常是完完全全的对象,在其上可定义任意方法。这种方法的主要用途是为捕获异常的代码提供额外的信息,这些信息与引起异常抛出的条件相关。如果缺乏这样的方法,程序员为弄出这些额外信息,就得去解析表示异常的字符串。这是很不好的实践(Item 10)。类极少定义字符串表示的细节,字符串表示会随实现的不同而变化,版本的不同而变化。因此,解析表示异常字符串的代码很可能是不兼容的、脆弱的。

       因为受检查的异常一般表明可恢复条件,为这样的异常提供一些方法就更为重要,这些方法提供了帮助调用者恢复程序运行的信息。例如,因信用卡上的余额不足而使购物失败,从而抛出一个受检查的异常,该异常就应提供了一个方法以获得不足的金额,购物者就可以补足这个金额(从而使购物成功,程序继续运行-译注)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值