无论在咱们的工做仍是生活中,总会出现各类“错误”,各类突发的“异常”。不管咱们作了多少准备,多少测试,这些异常总会在某个时间点出现,若是处理不当或是不及时,每每还会致使其余新的问题出现。因此咱们要时刻注意这些陷阱以及须要一套“最佳实践”来创建起一个完善的异常处理机制。web
首先,这里我画了一个异常分类的结构图。模块化
在JDK中,Throwable是全部异常的父类,其下分为”Error“和”Exception“。Error意味着出现了不可控的严重错误,例如OutOfMemoryError。Exception则细分为两类,受检异常(check)须要咱们手动try/catch或者在方法定义中throws,编译器在编译的时候会检查其合法性。非受检异常(uncheck)则不须要咱们提早处理。这些简单的概念对于开发人员来讲都是必须掌握的,这里就展现个图例,不作详细的描述了,咱们的”正餐“还在后面。工具
说到异常处理,这里就不得不提try/catch/finally。try不能够单独存在,要么搭配catch,要么搭配finally,或者三者并存。
一、try代码块:监视代码块的执行,发现对应的的异常则跳转至catch,若无catch则直接到finally块。
二、catch代码块:发生对应的异常会执行里面的代码,要么处理,要么向上抛出。
三、finally代码块:不论是否有异常,都必执行,通常用来清理资源,释放链接等。然而有如下几种状况不会执行到这里的代码。性能
下面介绍两个咱们在使用tcf的时候可能会遇到的陷阱。测试
代码1spa
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的值,假如业务逻辑比较复杂,这里是很容易掉坑的,不利于排查错误。code
代码2orm
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代码块外面。cdn
好了,前面简单介绍了异常的分类以及try/catch/finally的注意事项,如今能够总结一下咱们在异常处理的时候有哪些”最佳实践“了。blog
小小的异常,有大大的学问,你以为呢?