详解Java异常处理最佳实践及陷阱防范

 更新时间:2019年04月15日 10:31:00   作者:深夜里的程序猿  
这篇文章主要介绍了Java异常处理最佳实践及陷阱防范,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

不管在我们的工作还是生活中,总会出现各种“错误”,各种突发的“异常”。无论我们做了多少准备,多少测试,这些异常总会在某个时间点出现,如果处理不当或是不及时,往往还会导致其他新的问题出现。所以我们要时刻注意这些陷阱以及需要一套“最佳实践”来建立起一个完善的异常处理机制。

异常分类

首先,这里我画了一个异常分类的结构图。

在JDK中,Throwable是所有异常的父类,其下分为”Error“和”Exception“。Error意味着出现了不可控的严重错误,例如OutOfMemoryError。Exception则细分为两类,受检异常(check)需要我们手动try/catch或者在方法定义中throws,编译器在编译的时候会检查其合法性。非受检异常(uncheck)则不需要我们提前处理。这些简单的概念对于开发人员来说都是必须掌握的,这里就展示个图例,不做详细的描述了,我们的”正餐“还在后面。

重新认识try/catch/finally

说到异常处理,这里就不得不提try/catch/finally。try不可以单独存在,要么搭配catch,要么搭配finally,或者三者并存。

1、try代码块:监视代码块的执行,发现对应的的异常则跳转至catch,若无catch则直接到finally块。

2、catch代码块:发生对应的异常会执行里面的代码,要么处理,要么向上抛出。

3、finally代码块:不管是否有异常,都必执行,一般用来清理资源,释放连接等。然而有以下几种情况不会执行到这里的代码。

  1. 代码执行流程未进入try代码块。
  2. 代码在try代码块中发生死循环、死锁等状态。
  3. 在try代码块中执行了System.exit()操作。

try/catch/finally陷阱

下面介绍两个我们在使用tcf的时候可能会遇到的陷阱。

代码1

public class TCFDemo {
  public static void main(String[] args) {
    //11
    System.out.println(returnVal());
  }

  static int returnVal(){
    int a = 1;
    int b = 10;
    try{
      return ++a;
    }finally {
      return ++b;
    }
  }
}

陷阱1:在finally中添加return语句,这样会覆盖掉try代码return的值,假如业务逻辑比较复杂,这里是很容易掉坑的,不利于排查错误。

代码2

public class TCFDemo {
  public static void main(String[] args) {
    Lock lock = new ReentrantLock();
    try{
      //有可能加锁失败
      lock.lock();
      //dost
    }finally {
      lock.unlock();
    }
  }
}

陷阱2:由于lock方法在加锁的时候有可能会抛出Uncheck异常,如果在try代码块中,必然会执行unlock方法,此时由于并没有加锁成功,所以会抛出IllegalMonitorStateException,这样一来后者的异常就覆盖掉了前者加锁失败的异常信息,所以我们应该把加锁的方法挪至try代码块外面。

最佳实践

好了,前面简单介绍了异常的分类以及try/catch/finally的注意事项,现在可以总结一下我们在异常处理的时候有哪些”最佳实践“了。

  1. 当需要向上抛出异常的时候,需根据当前业务场景定义具有业务含义的异常,优先使用行业内定义的异常或者团队内部定义好的。例如在使用dubbo进行远程服务调用超时的时候会抛出DubboTimeoutException,而不是直接把RuntimeException抛出。
  2. 请勿在finally代码块中使用return语句,避免返回值的判断变得复杂。
  3. 捕获异常具体的子类,而不是Exception,更不是throwable。这样会捕获所有的错误,包括JVM抛出的无法处理的严重错误。
  4. 切记更别忽视任何一个异常(catch住了不做任何处理),即使现在能确保不影响逻辑的正常运行,但是对于将来谁都无法保证代码会如何改动,别给自己挖坑。
  5. 不要使用异常当作控制流程来使用,这是一个很奇葩也很影响性能的做法。
  6. 清理资源,释放连接等操作一定要放在finally代码块中,防止内存泄漏,如果finally块处理的逻辑比较多且模块化,我们可以封装成工具方法调用,代码会比较简洁。

结尾

小小的异常,有大大的学问,你觉得呢?

以上所述是小编给大家介绍的Java异常处理最佳实践及陷阱防范详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • JAVA实现简单系统登陆注册模块

    JAVA实现简单系统登陆注册模块

    这篇文章主要介绍了一个简单完整的登陆注册模块的实现过程,文章条理清晰,在实现过程中加深了对相关概念的理解,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2015-07-07
  • Mybatis-Plus自定义集合类型的类型处理器详解

    Mybatis-Plus自定义集合类型的类型处理器详解

    这篇文章主要介绍了Mybatis-Plus自定义集合类型的类型处理器详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • java并发问题概述

    java并发问题概述

    这篇文章主要介绍了java并发问题概述,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • idea 实现git rebase操作应用场景

    idea 实现git rebase操作应用场景

    本文结合idea工具进行rebase的各种场景的操作,借助工具更能直观地观察到分支之间地操作差异,方便我们理解rebase的各种操作以及场景的使用,对idea  git rebase操作知识感兴趣的朋友一起看看吧
    2024-01-01
  • Java C++ leetcode执行一次字符串交换能否使两个字符串相等

    Java C++ leetcode执行一次字符串交换能否使两个字符串相等

    这篇文章主要为大家介绍了Java C++ leetcode1790执行一次字符串交换能否使两个字符串相等,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • MyEclipse 2016 CI 4新增BootStrap模板

    MyEclipse 2016 CI 4新增BootStrap模板

    MyEclipse2016是一款全球使用最为广泛的企业级开发环境程序,这篇文章主要介绍了MyEclipse 2016 CI 4新增BootStrap模板的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-06-06
  • Java中==运算符与equals方法的区别及intern方法详解

    Java中==运算符与equals方法的区别及intern方法详解

    这篇文章主要介绍了Java中==运算符与equals方法的区别及intern方法详解的相关资料,需要的朋友可以参考下
    2017-04-04
  • Java使用正则表达式(regex)匹配中文实例代码

    Java使用正则表达式(regex)匹配中文实例代码

    本文给大家分享java使用正则表达式匹配中文的实例代码,以及java中要匹配中文的正则表达式两种写法,感兴趣的朋友通过本文一起看看吧
    2016-12-12
  • 详解Java Ajax jsonp 跨域请求

    详解Java Ajax jsonp 跨域请求

    本篇文章主要介绍了详解Java Ajax jsonp 跨域请求,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • Springboot Activemq整合过程代码图解

    Springboot Activemq整合过程代码图解

    这篇文章主要介绍了Springboot Activemq整合过程代码图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02

最新评论