Java基础之回味finally
平时大家try…catch…finally语句用的不少,知道finally块一定会在try…catch..执行结束时执行,但是具体是在什么时候执行呢,今天我们一起来看下。
public static int test1(){ int i = 0; try{ return ++i; }finally{ ++i; } }
上面的方法,执行结果返回1。finally块中的代码会不会没有执行,我们再试试。
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是一样的,有兴趣的朋友可以试试。
作者:wangl110
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。