【第39条】只针对不正常的条件才使用异常

《第8章 异常》

 

    异常是Java语言中非常重要、而又容易被轻视的、一个出于非常奇妙的地位的一个东东。这一章讲了关于有效使用异常的指导性原则。

 

【第39条】只针对不正常的条件才使用异常

 

    异常只应该被用于不正常的情况,它们永远不应该被用于正常的控制流。书中举了一个特殊的例子,在这个例子中,循环的结束条件是当数组下标出界时引发的一个 ArrayIndexOutOfBoundsException。这段程序的作者“自作聪明”地认为“传统”的 for 循环 或 while 循环 需要在每次进行大小判断,是要额外耗费时间的,所以“发明”了这种每次执行完循环体不必“浪费时间去比较大小”的写法,直到产生“下标越界”异常后结束循环。

 

    而事实上,JVM会对那些“传统”的 for while 循环做各种各样的性能优化,而绝不会去对 try-catch 块做出什么优化。这样的“自作聪明”其实反而降低了性能。同时,这样的“非常规”写法,也是代码的可读性急剧下降。而且这种依靠通过异常来达到程序流控制目的的代码,很容易与bug等异常混淆在一起,给调试工作带来了很大的麻烦。

 

    这一条原则,同样也对API的设计者有所启示。当我们在写一个具有状态相关的方法时,不应该强迫调用者为了正常的控制流而使用异常。具有状态相关的方法,简单的说就是不是在什么情况下都可以使用,只有特点条件下才可以。例如,只有在数据库已连接的状态下,才可以调用的数据库操作方法 等。

 

    进一步解释一下,就是说,我们应该通过一个状态检查方法来控制流,而不是使用异常:

// 应该这样
if db.isConnected() {
    result = db.select(sql);
}


// 而不该这样
try{
    result = db.select(sql);
}catch (DatabaseNotConnectException e){
.....
}

    如果称这种方式为“状态检测法”,那么还有一种方式可以称之为“可被识别的返回值”方式。比如,在上面的例子中,既不使用 if 也不适用 try-catch,在 select 方法中,当数据库尚未连接时,不是抛出一个DatabaseNotConnectException,而是返回 null 。

 

    那么正两种方式该如何选择呢?首先,当null是正常情况下本身就可能的一个返回值时“可被识别的返回值”就不适用了,例如书中Iterator.next()的例子。其次,在多线程的程序中,检查状态和真正调用之间,状态可能会被其他线程改变,这种时候就可以使用“可被识别的返回值”方式。最后,当不存在状态检测不稳定的前提下,可以忽略状态检测本身的性能耗费而选用“状态检测法”。

 

 

   总结:这一条中的前一半,讲的不可用异常来控制程序流,估计我们应该不会犯这样的错误,就当是“无则加免”吧。后一半,讲的两种“方式”倒是非常值得学习和借鉴的。

 

 

 

【Effective Java 学习笔记】系列连载专题请见:
http://tonylian.iteye.com/categories/64208

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值