平时你们try…catch…finally语句用的很多,知道finally块必定会在try…catch..执行结束时执行,可是具体是在何时执行呢,今天咱们一块儿来看下。html
public static int test1(){ int i = 0; try{ return ++i; }finally{ ++i; } }
上面的方法,执行结果返回1。finally块中的代码会不会没有执行,咱们再试试。java
public static int test2(){ int i = 0; try{ return ++i; }finally{ return ++i; } }
test2()执行结果返回2。能够确定的是,finally块执行了。咱们对比test1()和test2(),能够得出以下结论:
1. finally块会在try块return语句执行后,执行结果返回前执行;
2. 若是finally块中有return语句,而且是返回的是值类型,则会覆盖try块的return结果。
那么,若是返回的不是值,而是对象呢?
public static Integer test3(){ Map<Integer,Integer> map = new HashMap<>(); map.put(0, new Integer(0)); try{ map.put(0, new Integer(1)); return map.get(0); }finally{ map.put(0, new Integer(2)); } } public static Integer test4(){ Map<Integer,Integer> map = new HashMap<>(); map.put(0, new Integer(0)); try{ map.put(0, new Integer(1)); return map.get(0); }finally{ map = null; } }
显然,finally块确定执行了,可是test3()和test4()返回的均是1。咱们将test3()稍微修改下,改为下面的test5(),
而后执行System.out.println(test5().get(0)),会发现执行结果是2.
public static Map<Integer,Integer> test5(){ Map<Integer,Integer> map = new HashMap<>(); map.put(0, new Integer(0)); try{ map.put(0, new Integer(1)); return map; }finally{ map.put(0, new Integer(2)); } }
对比test3(),test4(),test5()的代码和返回结果,估计你们都发现了,这其实仍是java的值传递问题,只是平时可能做为形参出现的更多些,这里是做为返回值。
当返回的是引用地址时,只有finally块中修改的是返回地址对象内的属性,try块的return结果才会被修改。方法test5(),返回map对象的引用地址,finally块中对map作的修改,影响到try块return的map;而test3()和test4(),返回的是Integer对象的引用地址,finally块中对map作的修改,并不会对其有影响(从jvm内存模型的角度去看,会更好理解,但是图我不知道怎么画会比较形象[难过])。
本文中的方法demo中都没有catch,可是catch块对于finally块,和try是同样的,有兴趣的朋友能够试试。