finally关键字

来源:互联网 发布:linux设备驱动开发详解 编辑:程序博客网 时间:2024/06/11 12:03

点击打开链接

面试官题目


什么时候用到finally呢?finally语句在try或catch中的return语句执行之后,还是return返回之前执行呢?



考点分析



这个题目也是考查异常相关的。对于这个题目,我们通过代码来验证我们的答案,因为有异议的知识点,代码是最有说服力的。对于编程,希望你记住“不与人争辩,一切用代码说话”。


回答


什么时候用到finally呢?

某些事物(除内存外)在异常处理完后需要恢复到原始状态,如:开启的文件,网络连接等。


finally语句在try或catch中的return语句执行之后,还是return返回之前执行呢?

这个问题是一个很经典的问题,经常被面试官问,如果自己不去实验一下,可能判断就会出错。我们结合代码来分析一下。

下面我们通过4个demo来得出最终结论。



1

private static int test1() {

        int i = 1;

        try {

            System.out.println("try...");

            return i += 10;

        } catch (Exception e) {

            System.out.println("catch...");

        } finally {

            i++;

            System.out.println("finally...");

            System.out.println("i=" + i);

        }

        return i;

}


执行结果:

try...

finally...

i=12

test1:11


总结:finally代码块是在try代码块中的return语句执行之后,返回之前执行的。



2


private static int test2() {

        int i = 1;

        try {

            System.out.println("try...");

            return i += 10;

        } catch (Exception e) {

            System.out.println("catch...");

        } finally {

            i++;

            System.out.println("finally...");

            System.out.println("i=" + i);

            return i;

        }

}


执行结果: 

test2:12

try...

finally...

i=12


总结:finally代码块中的return语句覆盖try代码块中的return语句。



3

private static Map<String, String> test3() {

        Map<String, String> map = new HashMap<String, String>();

        map.put("KEY", "INIT");

        try {

            System.out.println("try...");

            map.put("KEY", "TRY");

            return map;

        } catch (Exception e) {

            System.out.println("catch...");

            map.put("KEY", "CATCH");

        } finally {

            System.out.println("finally...");

            map.put("KEY", "FINALLY");

            map = null;

        }

        return map;

}


执行结果: 

try...

FINALLY

finally...


总结: 如果finally语句中没有return语句覆盖返回值,那么原来的返回值可能因为finally里的修改而改变也可能不变。传值类型的返回值:不变;传址类型的返回值:会变。


这里引入来一个新的问题,怎么判断一个变量是传值还是传址?传值:8种基本数据类型及其包装类,字符常量。传址:数组和对象。



4

private static int test4() {

        int i = 1;

        try {

            System.out.println("try...");

            i = i / 0;

            return i += 10;

        } catch (Exception e) {

            System.out.println("catch...");

            return i;

        } finally {

            i++;

            System.out.println("finally...");

            System.out.println("i=" + i);

        }

}

执行结果: 

try...

catch...

finally...

i=2

1


总结: try代码块中的return语句在异常的情况下不会被执行,这样具体返回哪个看情况;catch中的return执行情况与未发生异常时try中return的执行情况完全一样。


汇总

根据上面的分析,咱们来汇总一下答案:

  1. try语句没有被执行,如在try语句之前就返回了,这样finally语句就不会执行;因此说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到。

  2. 如果在try代码块中执行System.exit(0)语句;那么将终止Java虚拟机JVM,因此,finally语句也不会被执行到。

  3. finally块的语句在try或catch中的return语句执行之后返回之前执行且finally里的修改语句可能影响也可能不影响try或catch中return已经确定的返回值,如果返回值类型为传址类型,则影响;传值类型,则不影响。若finally里也有return语句则覆盖try或catch中的return语句直接返回。