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是一样的,有兴趣的朋友可以试试。
posted @ 2019-05-08 23:42  wangl110  阅读(158)  评论(0编辑  收藏  举报