Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 356|回复: 0

Java异常处理之最佳实践

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-7-1 12:45:30 | 显示全部楼层 |阅读模式

    引言:

    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代码块

     





    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-1 13:02 , Processed in 0.061373 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表