思考一个问题

Java异常捕获机制try…catch…finally块中的finally语句是否一定会被执行?起码在以下两种情况下是不会被执行的:
1.在try之前就返回了,try没有执行到。
2.try中System.exit(0)来终止JVM。JVM都终止了,自然finally也就不会再执行了

栗证

public class FinallyTest1 {
    public static void main(String []args){
        System.out.println(test1());
    }

    private static int test1() {
        int b = 20;
        try {
            System.out.println("try语句块");
            return b+=80;
        }catch (Exception e){
            System.out.println("catch语句块");
        }finally {
            System.out.println("finally语句块");
            if (b>25){
                System.out.println("b>25,b="+b);
            }
        }
        return b;
    }
}

输出结果如下:

try语句块
finally语句块
b>25,b=100
100

说明return语句已经执行了,然后再去执行finally,等finally执行完后,再返回来return 结果。这里已经得到了验证,可是如果finally中也有return语句,那该咋办呢?

finally块中的return会覆盖try块中的return

public class FinallyTest2 {
    public static void main(String []args){
        System.out.println(test2());
    }

    private static int test2() {
        int b = 20;
        try {
            System.out.println("try语句块");
            return b+=80;
        }catch (Exception e){
            System.out.println("catch语句块");
        }finally {
            System.out.println("finally语句块");
            if (b>25){
                System.out.println("b>25,b="+b);
            }
            return 200;
        }
    }
}

输出结果:

try语句块
finally语句块
b>25,b=100
200

这里finally语句块中有return,就直接return结束了,try语句块中的return根本不会再执行了。
这里再抛出另一个思考:如果finally中没有return,但修改了b,那么try中return的是原始值还是新值?

finally中没有return,原来的返回值变不变说不准

案例1:

public class FinallyTest3 {
    public static void main(String []args){
        System.out.println(test3());
    }

    private static int test3() {
        int b = 20;
        try {
            System.out.println("try语句块");
            return b+=80;
        }catch (Exception e){
            System.out.println("catch语句块");
        }finally {
            System.out.println("finally语句块");
            if (b>25){
                System.out.println("b>25,b="+b);
            }
            b=150;
        }
        return 2000;
    }
}

输出结果:

try语句块
finally语句块
b>25,b=100
100

案例2:

public class FinallyTest4 {
    public static void main(String []args){
        System.out.println(getMap().get("key").toString());
    }
    public static Map<String,String> getMap(){
        HashMap<String, String> map = new HashMap<>();
        map.put("key","init");

        try {
            map.put("key","try");
            return map;
        }catch (Exception e){
            map.put("key","catch");
        }finally {
            map.put("key","finally");
            map=null;
        }
        return map;
    }
}

输出结果:

finally

案例1中finally的“干扰”没有起作用,案例2中finally的map.put(“key”,“finally”);起作用了,但是map=null并没起到作用。这里涉及到的就是java到底是传值还是传址了。简单来讲,java只有传值,没有传址,所以map=null;没有起作用。

try块中的return在异常情况下不会执行

public class FinallyTest5 {
    public static void main(String []args){
        System.out.println(test5());
    }

    private static int test5() {
        int b = 20;
        try {
            System.out.println("try语句块");
            b=b/0;
            return b+=80;
        }catch (Exception e){
            b+=15;
            System.out.println("catch语句块");
        }finally {
            System.out.println("finally语句块");
            if (b>25){
                System.out.println("b>25,b="+b);
            }
            b+=50;
        }
        return b;
    }
}

输出结果:

try语句块
catch语句块
finally语句块
b>25,b=35
85

这里try中发生了异常,try中没有return而是被catch,最后到了finally执行了了finally块中的命令

异常发生,catch中的return执行情况和未发生异常的try中return执行情况一样

public class FinallyTest6 {
    public static void main(String []args){
        System.out.println(test6());
    }

    private static int test6() {
        int b = 20;
        try {
            System.out.println("try语句块");
            b=b/0;
            return b+=80;
        }catch (Exception e){
            System.out.println("catch语句块");
            return b+=15;
        }finally {
            System.out.println("finally语句块");
            if (b>25){
                System.out.println("b>25,b="+b);
            }
            b+=50;
        }
    }
}

输出结果:

try语句块
catch语句块
finally语句块
b>25,b=35
35

异常发生后,catch中的return语句先执行,确定返回值后再去执行finally,然后再返回catch中的return,finally中对b的改变不造成影响。

总结

finally块中的语句,在try或catch中的return语句执行之后、返回之前执行。而且finally语句中的“干扰”可能或不可能影响try、catch中return已经确定的返回值。若finally中也有return则覆盖try、catch中的return语句直接返回。