Java基础之回味finally

平时你们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是同样的,有兴趣的朋友能够试试。
相关文章
相关标签/搜索