博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java异常处理之最佳实践
阅读量:5030 次
发布时间:2019-06-12

本文共 3078 字,大约阅读时间需要 10 分钟。

引言:

publicvoidconsumeAndForgetAllExceptions(){
    try{
        ...some code that throws exceptions
    } catch(Exception ex){
        ex.printStacktrace();
    }
}
采用上面这种方式处理异常时,catch代码段接管控制权,然后catch段之后代码继续执行,好像什么都没有发生。
 
publicvoidsomeMethod() throws Exception{
}
该方法内可能并不会抛出异常
总结:忽略异常或随意抛出异常是常见现象。
 

异常的本质 

广义的讲,抛出异常分三种不同的情况: 
- 编程错误导致的异常:譬如NullPointerException和IllegalArgumentException),代码通常对编程错误没有什么对策。 
- 客户端的错误导致的异常:试图违背制定的规则,例如读写文件流的关闭操作。
- 资源错误导致的异常:当获取资源错误时引发的异常。例如,系统内存不足,或者网络连接失败。
 
对于Java作为第一个使用checked exception的主流面向对象语言而言,高层必须catch或throw,若不能有效的处理异常的话,就会在API和代码之间造成负担。
publicList getAllAccounts() throws
    FileNotFoundException, SQLException{
    ...
}
Checked exception被诟病破坏封装性:getAllAccounts使得调用者必须处理这两个异常,但调用者不知道什么文件找不到&什么数据库语句失败,也不知道该提供什么文件系统或者数据库的事物层逻辑。这使得方法与调用者之间形成不恰当的紧耦合关系。
 
 

设计API的最佳实践

1. 根据客户端如何应对Exception决定使用checked exception还是unchecked exception
分析:若客户端可以采取行动恢复的建议采用checked exception
unchecked exception建议多用,因为它不强迫客户端必须处理,会扩散直到客户端想处理。建议采用Java定义好的异常类,更有利于代码的易读性。
 
2. 保持封装性
不要将针对某特定实现的checked exception用到更高的层次中去。
例如不要让SQLException扩散到逻辑层去,因为逻辑层是不需要知道SQLException。解决办法:a.客户端有相应应对措施时,转换SQLException为另一个checked exception
b.若客户端无法处理,转换SQLException为unchecked exception
4. 将异常文档化
你可以采用Javadoc’s @throws标签将你的API抛出的checked和unchecked exception都文档化。
3. 不要忽略异常当一个API方法抛出checked exception时,如果对你没什么意义,直接转换成unchecked exception抛出,而不要仅仅用空的catch来忽略该异常。
处理示例:
之前代码:
publicvoiddataAccessCode(){
    try{
        ..some code that throws SQLException
    }catch(SQLException ex){
        ex.printStacktrace();
    }
}
上面catch段仅仅抑制住了异常,什么都没做,改成下面部分后,
publicvoiddataAccessCode(){
    try{
        ..some code that throws SQLException
    }catch(SQLException ex){
        thrownewRuntimeException(ex);
    }
}
此时,若发生SQLException异常,会抛给高层RuntimeException异常,使得当前线程挂起并爆出异常信息。此时逻辑层也不需要进行不必要的异常处理,尤其是逻辑层不知道怎么处理SQLException。
补充:若逻辑层打算采取恢复措施应对SQLException,那可以抛出自定义的checked exception。
 
4. 如果自定义的异常没有提供有用的信息的话,请不要创建它们。
a.当前异常发生时,给出一些相关的数据信息
publicclassDuplicateUsernameException
    extendsException {
    publicDuplicateUsernameException
        (Stringusername){....}
    publicStringrequestedUsername(){...}
    publicString[] availableNames(){...}
}
b.若不想获取详细信息,抛出标准异常也可以。
thrownewException("Username already taken");
注:抛出什么异常参见最佳实践第一点
 
 
 

使用异常的最佳实践

1. 记得释放资源

publicvoiddataAccessCode(){
    Connection conn = null;
    try{
        conn = getConnection();
        ..some code that throws SQLException
    }catch(SQLException ex){
        ex.printStacktrace();
    } finally{
        DBUtil.closeConnection(conn);
    }
}
 
classDBUtil{
    publicstaticvoidcloseConnection
        (Connection conn){
        try{
            conn.close();
        } catch(SQLException ex){
            logger.error("Cannot close connection");
            thrownewRuntimeException(ex);
        }
    }
}
DBUtil关闭连接工具类,最重要的部分在于finally,无论异常发不发生都会执行关闭连接操作,如果关闭发生异常会抛出一个RuntimeException。
 

2. 不要使用异常作控制流程之用

public
void
useExceptionsForFlowControl() {
    
try
{
        
while
(
true
) {
            
increaseCount();
        
}
    
}
catch
(MaximumCountReachedException ex) {
    
}
    
//Continue execution
}
 
public
void
increaseCount()
    
throws MaximumCountReachedException {
    
if
(count >=
5000
)
        
throw
new
MaximumCountReachedException();
}
生成栈回溯的代价很昂贵,栈回溯的价值是在于调试,而不是流程控制中。
 

3 不要catch最高层次的exception

try{
..
}catch(Exception ex){
}
上面这种写法不建议,应该对具体异常分类处理。
 

4.尽量减小try代码块

 

转载于:https://www.cnblogs.com/linux007/p/5782708.html

你可能感兴趣的文章
微信架构(转)
查看>>
Web项目中的路径问题
查看>>
js随机数的取整
查看>>
关于解析漏洞
查看>>
十大经典预测算法(六)---集成学习(模型融合算法)
查看>>
用php做一个简单的注册用户功能
查看>>
一款基于css3的3D图片翻页切换特效
查看>>
Feign使用Hystrix无效原因及解决方法
查看>>
Sizeof与Strlen的区别与联系
查看>>
hadoop2.2.0_hbase0.96_zookeeper3.4.5全分布式安装文档下载
查看>>
Flutter 贝塞尔曲线切割
查看>>
golang 的编译安装以及supervisord部署
查看>>
阿里架构师,讲述基于微服务的软件架构模式
查看>>
Eclipse导入maven项目时,Pom.xml文件报错处理方法
查看>>
01、JAVA开发准备
查看>>
asp.net mvc 错误处理 - 自定义报错处理,生成错误日志
查看>>
[转]jQuery 选择器和dom操作
查看>>
Jenkins+Maven+SVN快速搭建持续集成环境(转)
查看>>
杜教筛
查看>>
《Ext JS模板与组件基本知识框架图----模板》
查看>>