侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Java异常那些不得不说的事

Java  /  管理员 发布于 5年前   578

    一、在finally块中做数据回收操作

    比如数据库连接都是很宝贵的,所以最好在finally中关闭连接。

    JDBCAgent jdbc = new JDBCAgent();try{jdbc.excute("select * from ctp_log");}catch(SQLException e){...}finally{jdbc.close();}

     

     

     

    二、不要在异常finally块中定义返回值

    如下代码,虽然有很多返回值,但如果真的执行,该代码的返回值永远是3,因为finally是最终执行代码,将其它返回值全部覆盖了!

    try{    if(x = 1){      return throw new RuntimeException();    }else{      return 1;    }  }catch(Exception e){    return 2;  }finally{    return 3;  }

     

     

     

    三、覆写Exception的fillInStackTrace方法能提高异常性能

    异常性能差是因为fillInStackTrace方法,该方法是带锁的并且需要填充线程异常栈信息。

    而我们的业务类异常是不需要记录异常栈的,可以考虑覆写fillInStackTrace方法减小性能开支(据说覆写该方法能提高10倍性能)。

    (注:什么是业务类,参照第四点)

    public class AccountException extends Exception {    public Throwable fillInStackTrace() {          return this;      }}

     

     

     

    四、业务上的错误使用异常更加OOP

    以登录为例,简单的登录方法通过返回boolean即可确认是否登录成功,但如果功能日趋复杂怎么办?通过抛出业务类异常的方式来解析错误信息可读性非常好。

    try{  userManager.login(account,passowrd,identify);}catch(AccountException e){    //账号出错  }catch(PasswordException e){    //密码出错  }catch(IdentifyException e){  //验证码错误}catch(AccountDisableException e){  //账号被禁用}

     

     

     

    五、使用正确的log记录异常信息

    Log logger = LogFactory.getLog(Demo.class);try{  }catch(SQLException e){ throw new BusinessException(e);           //√发生该异常会影响后续数据完整性的时候,应该抛出中止操作 logger.error(e.getLocalizedMessage(),e);  //√记录完整的log日志方便调试 log.error(e);                             //×这种记录方式只能记录很少的异常信息(连异常发生的位置都没有,记了白记) e.printStackTrace();                      //×仅仅将异常打到控制台,开发调试还可以,一旦到生产环境就很难跟踪异常 System.out.print(e);                      //×同上}

     

     

     

    六、除了记录异常,记得记录详细参数信息

    很多时候通过logger.error(e.getLocalizedMessage(),e)这种记录日志的方式都不一定分析出异常原因。

    比如出现一个SQL异常,log日志可能会这样提示:ORA-00936: 缺少表达式。试问这样的错误你能分析这句SQL到底哪儿出了问题吗?不能!所以记录日志的时候最好是把SQL及参数都打印出来,如下例所示。

    但记录日志要有分寸,别把客户的机密信息记录出来,如果被发现,我们会负责的!

    public List find(Long id,String name){  String sql = ......;  try{  JdbcAgent.excute(sql);  }catch(Exception e){  logger.error("sql异常:"+sql+" 参数ID:"+id+",参数name:"+name,e);  }}

     

     

    (注:作为研发你可能会说:我通过Eclipse debugger调试就可以知道原因了。但从长远考虑:假如系统已经部署到客户环境上,他们允许你debugger调试吗?不能!所以最好的求助工具就是详细的log日志!)

     

    七、从子到父顺序捕获异常

    如下所示,假如抛出的是BusinessException异常,那么第二个catch就能捕获到。

    如果catch(Exception e)在catch(BusinessException e)之前,则该异常会被catch(Exception e)捕获而不会进catch(BusinessException e)。

    try{}catch(RuntimeException e){}catch(BusinessException e){//BusinessException extends Exception}catch(Exception e){}

     

     

     

    八、使用isInfoEnabled和isDebugEnabled

    在看spring和apache等开源体系下的代码时,你会发现在记录log日志时总是看到如下风格的代码:

    if (logger.isDebugEnabled()) {    logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");}if (logger.isInfoEnabled()) {long elapsedTime = System.currentTimeMillis() - startTime;logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");}

     

     

    为什么记录debug和info日志前要加个判断?其实原因很简单:提高效率!如上代码所示,在记录日志时进行了字符串拼接,要知道这是会消耗一定资源的。假如当前log日志级别是error,则debug和info是不会被输出的,如果加了if判断则log.debug/info中的字符串拼接就不会执行,自然提高了效率。

    在小系统看不出差距,但如果是高并发的系统下,少执行一句代码能明显减小服务器的压力,精细化的代码是有必要的!

     

    注意:下面这样的代码是提高不了性能的,因为在if之前就已经准备好log信息:

    long elapsedTime = System.currentTimeMillis() - startTime;String info = "Root WebApplicationContext: initialization completed in " + elapsedTime + " ms";if (logger.isInfoEnabled()) {logger.info(info);}

     

     



  • 上一条:
    摘抄笔记--《编写高质量代码:改善Java程序的151个建议》
    下一条:
    Java Hotspot: Remove the Permanent Generation
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在java中实现的脱敏工具类代码示例分享(0个评论)
    • zookeeper安装流程步骤(0个评论)
    • 在java中你背的“八股文”可能已经过时了(2个评论)
    • 在php8.0+版本中使用属性来增加值代码示例(3个评论)
    • java 正则表达式基础,实例学习资料收集大全 原创(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-11
    • 2018-03
    • 2020-03
    • 2023-05
    • 2023-11
    • 2024-01
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客