正确使用异常

最近发现做过的系统,对异常没有很好的处理,看了些资料,整理如下:

 

1,java异常分类

(1)Checked exception: 这类异常都是Exception的子类,需要程序捕获处理的。
(2)Unchecked exception: 这类异常都是RuntimeException的子类,虽然RuntimeException同样也是Exception的子类,但是它们是特殊的,它们 不能通过程序来试图解决,所以称为Unchecked exception,不需要显示抛出和捕获。

 

2,使用例子

(1)

public void consumeAndForgetAllExceptions(){
    try {
        ...some code that throws exceptions
    } catch (Exception ex){
        ex.printStacktrace();
    }
}
上边的代码有什么问题么?

在回答以前让我们想想怎样才是正确的?是的,一旦程序碰到异常,它就该挂起程序而“做”点什么。那么上边的代码是这样子的么?看吧,它隐瞒了什 么?它把所有的“苦水”往肚里咽(在控制台打印出异常信息),然后一切继续,从表面上看就像什么都没有发生过一样……,很显然,上边代码达到的效果并不是 我们所期望的。

比如:通过界面删除数据时出错,没成功,但只是打印了错误日志,未做任何处理(如在界面提示),而且后面的操作还得以继续执行。


后来又怎样?

(2)
public void someMethod() throws Exception{
}

上边的代码又有什么问题?

很明显,上边的方法体是空的,它不实现任何的功能(没有一句代码),试问一个空方法体能抛出什么异常?当然Java并不阻止你这么干。最近,我也 遇到类似的情景,方法声明会抛出异常,但是代码中并没有任何“机会”来“展示”异常。当我问开发员为什么要这样做的时候,他回答我说“我知道,它确实有点 那个,但我以前就是这么干的并且它确实能为我工作。”

 

(3)用户登录

try { 
  UserManager.login(xx,xx);; 
....  
用户登陆以后的主事件流代码 
 
} catch (UserNotFoundException e); { 
... 
用户名称没有的事件处理,例如产生一个提示用户注册的页面 
} catch (PasswordNotMatchException e); {  
.... 
密码不对的事件处理,例如forward到重新登陆的页面 

 

(4)

public List getAllAccounts() throws
    FileNotFoundException, SQLException{
    ...
}

上边的方法抛出两个异常。客户端必须显示的对这两种异常进行捕获和处理即使是在完全不知道这种异常到底是因为文件还是数据库操作引起的情况下。因此,此时的异常处理将导致一种方法和调用之间不合适的耦合。

 

(5)

public void dataAccessCode(){
    try{
        ..some code that throws SQLException
    }catch(SQLException ex){
        ex.printStacktrace();
    }
}
上边的catch块紧紧打印异常信息而没有任何的直接操作,这是情有可原的,因为对于SQLException你还奢望客户端做些什么呢?(但是显然这种就象什么事情都没发生一样的做法是不可取的)那么有没有另外一种更加可行的方法呢?
public void dataAccessCode(){
    try{
        ..some code that throws SQLException
    }catch(SQLException ex){
        throw new RuntimeException(ex);
    }
}

 

3,如何正确使用的探讨

Client's reaction when exception happens 当异常发生时客户端的响应
Exception type 异常类型

Client code cannot do anything 客户端程序(调用方)什么也不能做
Make it an unchecked exception 使用unchecked exception

Client code will take some useful recovery action based on information in exception 根据异常信息,客户端程序的某些有用的操作可能修复此异常时
Make it a checked exception 使用checked exception

 

此外,尽量使用unchecked exception来处理编程错误:因为unchecked exception不用使客户端代码显示的处理它们,它们自己会在出现的地方挂起程序并打印出异常信息。Java API中提供了丰富的unchecked excetpion,譬如:NullPointerException , IllegalArgumentException 和 IllegalStateException等,因此我一般使用这些标准的异常类而不愿亲自创建新的异常类,这样使代码易于理解并避免的过多的消耗内 存。

 

1.  总是要做一些清理工作(Always clean up after yourself)

如果你使用一些资源例如数据库连接或者网络连接,请记住要做一些清理工作(如关闭数据库连接或者网络连接),如果你的API抛出Unchecked exception,那么你要用try-finally来做必要的清理工作:

public void dataAccessCode(){
    Connection conn = null;
    try{
        conn = getConnection();
        ..some code that throws SQLException
    }catch(SQLException ex){
        ex.printStacktrace();
    } finally{
        DBUtil.closeConnection(conn);
    }
}

class DBUtil{
    public static void closeConnection
        (Connection conn){
        try{
            conn.close();
        } catch(SQLException ex){
            logger.error("Cannot close connection");
            throw new RuntimeException(ex);
        }
    }
}

DBUtil是一个工具类来关闭Connection.有必要的说的使用的finally的重要性是不管程序是否碰到异常,它都会被执行。在上边的例子中,finally中关闭连接,如果在关闭连接的时候出现错误就抛出RuntimeException.

 

2. 不要使用异常来控制流程(Never use exceptions for flow control)

下边代码中,MaximumCountReachedException被用于控制流程:

public void useExceptionsForFlowControl() {
    try {
        while (true) {
            increaseCount();
        }
    } catch (MaximumCountReachedException ex) {
    }
    //Continue execution
}

public void increaseCount()
    throws MaximumCountReachedException {
    if (count >= 5000)
        throw new MaximumCountReachedException();
}



上边的useExceptionsForFlowControl()用一个无限循环来增加count直到抛出异常,这种做法并没有说让代码不易读,但是它是程序执行效率降低。

记住,只在要会抛出异常的地方进行异常处理。

 

3. 不要忽略异常

当有异常被抛出的时候,如果你不想恢复它,那么你要毫不犹豫的将其转换为unchecked exception,而不是用一个空的catch块或者什么也不做来忽略它,以至于从表面来看象是什么也没有发生一样。

 

4. 不要捕获顶层的Exception

unchecked exception都是RuntimeException的子类,RuntimeException又继承Exception,因此,如果单纯的捕获Exception,那么你同样也捕获了RuntimeException,如下代码:

try{
..
}catch(Exception ex){
}


一旦你写出了上边的代码(注意catch块是空的),它将忽略所有的异常,包括unchecked exception.

 

5. Log exceptions just once

    Logging the same exception stack trace more than once can confuse the programmer examining the stack trace about the original source of exception. So just log it once.

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值