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

JAVA异常设计原则

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

异常是面向对象语言非常重要的一个特性,良好的异常设计对程序的可扩展性、可维护性、健壮性都起到至关重要。 
JAVA根据用处的不同,定义两类异常 
    * Checked
Exception: 
Exception的子类,方法签名上需要显示的声明throws,编译器迫使调用者处理这类异常或者声明throws继续往上抛。 
    * Unchecked
Exception: 
RuntimeException的子类,方法签名不需要声明throws,编译器也不会强制调用者处理该类异常。 

异常的作用和好处: 
1. 分离错误代码和正常代码,代码更简洁。 
2. 保护数据的正确性和完整性,程序更严谨。 
3. 便于调试和排错,软件更好维护。 
…… 

相信很多JAVA开发人员都看到或听到过“不要使用异常来控制流程”,虽然这句话非常易于记忆,但是它并未给出“流程”的定义,所以很难理解作者的本意,让人迷惑不解。 

如果“流程”是包括程序的每一步执行,那异常就是用来控制流程的,它就是用来区分程序的正常流程和错误流程,为了更能明确的表达意思,上面这句话 应改成“不要用异常来控制程序的正常流程”。现在带来一个新的问题:如何区分程序正常流程和异常流程?我实在想不出一个评判标准,就举例来说明,大家思维 扩散下。 

为了后面更方便的表达,我把异常分成两类,不妥之处请谅解 

    * 系统异常:软件的缺陷,客户端对此类异常是无能为力的,通常都是Unchecked
Exception。 
    * 业务异常:用户未按正常流程操作导致的异常,都是Checked
Exception 

一个金币转账的例子:需求规定金币一次的转账范围是1~500,如果超过这个额度,就要提示用户金额超出单笔转账的限制。 
现在有以下几种场景: 
1. 转账的金额是由用户在页面随意输入的: 
因为值是用户随意输入的,所以给的值超出限定的范围肯定是司空见惯。我们当然不能把它(输入的值超出限定的范围)归结于异常流程,它应该属于正常流程。 
正确的实现如下: 
提供一个判断转账金币数量是否超出限定范围的方法 

Java代码
  1. private static final int MAX_PRE_TRANSFER_COIN = 500;  
  2.   
  3. public boolean isCoinExceedTransferLimits(int coin) {  
  4. return coin > MAX_PRE_TRANSFER_COIN;  
  5. }  

Action里先对值进行判断,若不合法,直接返回并提示用户 

2. 转账的额度是页面单选框(100、200、300、400、500)选择的: 
转账的额度用户不能轻易的更改,但是不排除有些无聊的人会借助其他工具(如,firebug)来修改。此类事件还是占少数的,我们就可以把它归结为非软件bug的异常事件—业务异常(Checked Exception)。 
正确的实现如下 

CoinExceedTransferLimitExcetion.java

Java代码
  1. //金币超出限定范围的异常类  
  2. public class CoinExceedTransferLimitExcetion extends Exception {  
  3. private static final long serialVersionUID = -7867713004171563795L;  
  4. private int coin;  
  5. public CoinExceedTransferLimitExcetion() {  
  6. }  
  7.   
  8. public CoinExceedTransferLimitExcetion(int coin) {  
  9. this.coin = coin;  
  10. }  
  11.   
  12. public int getCoin() {  
  13. return coin;  
  14. }  
  15.   
  16. @Override  
  17. public String getMessage() {  
  18. return coin + " is exceed transfer limit:500";  
  19. }  
  20. }  


//转账方法

Java代码
  1. private static final int MAX_PRE_TRANSFER_COIN = 500;  
  2.   
  3. public void transferCoin(int coin) throws CoinExceedTransferLimitExcetion {  
  4. if (coin > MAX_PRE_TRANSFER_COIN)  
  5. throw new CoinExceedTransferLimitExcetion(coin);  
  6. // do transfering coin  
  7. }  

3. 接口transferCoin(int coin)的规范里已经定了契约,调用transferCoin之前必须要先调用isCoinExceedTransferLimits判断值是否合法: 
虽然规范人人都要遵循,但毕竟只是规范,编译器无法强制约束。此时就需要用系统异常(Unchecked Exception)来保证程序的正确性,没遵守规范的就当做软件bug处理。 
正确的实现如下: 

Java代码
  1. public class CoinExceedTransferLimitExcetion extends RuntimeException {  
  2. private static final long serialVersionUID = -7867713004171563795L;  
  3.   
  4. public CoinExceedTransferLimitExcetion() {  
  5.   

抱歉!评论已关闭.