现在的位置: 首页 > 综合 > 正文

提高你的Java代码质量吧:受检异常尽可能转化为非受检异常

2013年10月10日 ⁄ 综合 ⁄ 共 1710字 ⁄ 字号 评论关闭

一、分析 

把所有受检查异常(Checked Exception)都转化为非受检查异常(UnChecked Exception)”这一想法是不现实的。受检查异常是正常逻辑的一种补偿处理手段,特别是对可靠性要求比较高的系统来说,在某些条件下必须抛出首检异常以便由程序进行补偿处理,也就说受检异常又合理的存在理由,那为什么需要把受检异常转化为非受检异

常? 

受检异常确实有不足的地方 

1.受检异常使接口声明脆弱 

例如,系统初始是这样设计一个接口的 

interfaceUser{  
    //修改用户名,抛出安全异常  
    publicvoid changePassword() throws MySecurityExcepiton; 
} 

随着系统的开发,User接口有了多个实现者,比如普通用户UserImpl、模拟用户MockUserImpl(用作测试或系统管理)、非实体用户NonUserImpl(如自动执行机、逻辑处理器等),此时如果发现changePassword方法可能还需要抛出RejectChangeException(拒绝修改异常,如自动执行正在处理任务时不能修改其密码),那就需要修改User接口了:changePassword方法增加抛出了RejectChangeException异常,这就会导致所有的User调用者都要追加对RejectChangeException异常的处理。 

这就产生了两个问题:一是异常是主逻辑的补充逻辑,修改一个补充逻辑,就会导致主逻辑的修改,这就出现了实现类“逆影响”接口的情景;二是实现类变更最终会影响到

调用者,破坏了封装性。 

2.受检异常使代码可读性降低 

一个方法增加了受简异常,则必须有一个调用者对异常进行处理,比如无受检异常方法doStuff()是这样调用的 
 
     
       
 

public static void main(String[] args){  
    doStuff();  
}

 doStuff方法一旦增加了首检异常就不一样了,代码如下:  

publicstatic void main(String[] args){  
    try{  
        doStuff();  
    }catch(Exceptione){  
        e.printStackTrace();  
    }  
} 

doStuff方法增加了throws Exception,调用者就必须至少增加4条语句来处理该异常,代码膨胀了许多,可读性也降低了。 

 3.受检异常增加开发工作量 

我们知道异常需要封装和传递,和封装才能让异常更容易理解,上层模块才能更好的处理问题,可这也会导致低层次的异常没完没了的封装,无端加重了开发的工作。 

比如,FileNotFoundException在持久层抛出,就需要定义一个MyException进行封装,并抛出到上一个层级,于是增加了开发量。 
 
 

受检查异常又这么多缺点,那有没有什么办法可以避免或减少这些确定呢?有,很简单的一个规则:将受检查异常转化为非检查异常即可,但是我们也不能把所有的受检查

异常转化为非受检查异常,原因是在编码上层模块不会知道下层模块会如何抛出何种非受检异常,只有通过规则或文档来约束,可以这样说: 

    a.受检异常提出的是“法律下的自由”,必须遵守异常的约定才能自由编写代码 

    b.非受检异常则是“协约性质的自由”,你必须告诉我你要抛出什么异常,否则不会处理

 

二、场景 

那么在开发和设计时,什么样的受检异常有必要转发为非受检异常呢?“尽可能”是以什么作为判断依据呢 

受检查异常转化为非受检异常是需要根据项目的场景来决定的。例如同样是刷卡,员工拿着自己的工卡到考勤机上打考勤,此时如果附近又磁场物质干扰,则考勤机可以把

这种受检异常转化为非首检异常,黄灯闪烁后不做任何登记,因为考勤失败这种场景不是“致命”的业务逻辑,出错了,重新刷一下即可。但是到银行网点刷卡取钱就不一样

了,拿着银行卡到银行取钱,同样有磁场干扰,刷不来,这种异常就必须登记处理,否则会称为威胁银行卡安全的事件。 

三、建议 

汇总成一句话:当受检异常威胁了系统的安全性、稳定性、可靠性、正确性的时候,则必须处理,不能转化为非受检异常,其它情况则可以转化为非受检异常。

抱歉!评论已关闭.