打字猴:1.700448785e+09
1700448785 编写高质量代码:改善Java程序的151个建议 [:1700438186]
1700448786 编写高质量代码:改善Java程序的151个建议 建议112:受检异常尽可能转化为非受检异常
1700448787
1700448788 为什么说是“尽可能”的转化呢?因为“把所有的受检异常(Checked Exception)都转化为非受检异常(Unchecked Exception)”这一想法是不现实的:受检异常是正常逻辑的一种补偿处理手段,特别是对可靠性要求比较高的系统来说,在某些条件下必须抛出受检异常以便由程序进行补偿处理,也就是说受检异常有合理的存在理由,那为什么要把受检异常转化为非受检异常呢?难道说受检异常有什么缺陷或不足吗?是的,受检异常确实有不足的地方:
1700448789
1700448790 (1)受检异常使接口声明脆弱
1700448791
1700448792 OOP(Object Oriented Programming,面向对象程序设计)要求我们尽量多地面向接口编程,可以提高代码的扩展性、稳定性等,但是一旦涉及异常问题就不一样了,例如系统初期是这样设计一个接口的:
1700448793
1700448794 interface User{
1700448795
1700448796 //修改用户名密码,抛出安全异常
1700448797
1700448798 public void changePassword()throws MySecurityException;
1700448799
1700448800 }
1700448801
1700448802 随着系统的开发,User接口有了多个实现者,比如普通的用户UserImpl、模拟用户MockUserImpl(用作测试或系统管理)、非实体用户NonUserImpl(如自动执行机、逻辑处理器等),此时如果发现changePassword方法可能还需要抛出RejectChangeException(拒绝修改异常,如自动执行机正在处理任务时不能修改其密码),那就需要修改User接口了:changePassword方法增加抛出RejectChangeException异常,这会导致所有的User调用者都要追加对RejectChangeException异常问题的处理。
1700448803
1700448804 这里产生了两个问题:一是异常是主逻辑的补充逻辑,修改一个补充逻辑,就会导致主逻辑也被修改,也就是出现了实现类“逆影响”接口的情景,我们知道实现类是不稳定的,而接口是稳定的,一旦定义了异常,则增加了接口的不稳定性,这是对面向对象设计的严重亵渎;二是实现的类变更最终会影响到调用者,破坏了封装性,这也是迪米特法则所不能容忍的。
1700448805
1700448806 (2)受检异常使代码的可读性降低
1700448807
1700448808 一个方法增加了受检异常,则必须有一个调用者对异常进行处理,比如无受检异常方法doStuff是这样调用的:
1700448809
1700448810 public static void main(String[]args){
1700448811
1700448812 doStuff();
1700448813
1700448814 }
1700448815
1700448816 doStuff方法一旦增加受检异常就不一样了,代码如下:
1700448817
1700448818 public static void main(String[]args){
1700448819
1700448820 try{
1700448821
1700448822 doStuff();
1700448823
1700448824 }catch(Exception e){
1700448825
1700448826 e.printStackTrace();
1700448827
1700448828 }
1700448829
1700448830 }
1700448831
1700448832 doStuff方法增加了throws Exception,调用者就必须至少增加4条语句来处理该异常,代码膨胀许多,可读写性也降低了,特别是在多个异常需要捕捉的情况下,多个catch块多个异常处理,而且还可能在catch块中再次抛出异常,这大大降低了代码的可读性。
1700448833
1700448834 (3)受检异常增加了开发工作量
[ 上一页 ]  [ :1.700448785e+09 ]  [ 下一页 ]