finally代码块的执行情况

本文包含以下知识点:

  • try里有return,finally还执行么?那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后
  • 如果执行finally代码块之前方法返回了结果,或者JVM退出了,finally块中的代码还会执行吗
  • 在什么情况下,finally语句不会执行

一、try里有return,finally怎么执行

1.finally块里的代码是在return之前执行的。

在异常处理中,无论是执行try还是catch,finally{}中的代码都会执行(除非特殊情况)。由于程序执行return就意味着结束对当前函数的调用并跳出这个函数体,因此任何语句要执行都只能在return前执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test {
public static int testFinally() {
try {
return 1;
} catch (Exception ex) {
return 2;
} finally {
System.out.println("execute finally");
}
}
public static void main(String[] args) {
int result = testFinally();
System.out.println(result);
}
}

运行结果

1
2
execute finally
1

2.此外,如果try-catch-finally中都有return,那么finally块中的return将会覆盖别处的return语句,最终返回到调用者那里的是finally中return的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Test {
public static int testFinally() {
try {
return 1;
} catch (Exception ex) {
return 2;
} finally {
System.out.println("execute finally");
return 3;
}
}
public static void main(String[] args) {
int result = testFinally();
System.out.println(result);
}
}

运行结果:

1
2
execute finally
3

return语句并不一定都是函数的出口,执行return时,只是把return后面的值复制了一份到返回值变量里去了。

3.此外,在try/catch中有return时,在finally块中改变基本类型的数据对返回值没有任何影响;而在finally中改变引用类型的数据会对返回结果有影响。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* try/catch中有return,在finally{}中改变基本数据类型、引用类型对运行结果的影响
*/
public class Test {
public static int testFinally1() {
int result1 = 1;
try {
return result1;
} catch (Exception ex) {
result1 = 2;
return result1;
} finally {
result1 = 3;
System.out.println("execute testFinally1");
}
}
public static StringBuffer testFinally2() {
StringBuffer result2 = new StringBuffer("hello");
try {
return result2;
} catch (Exception ex) {
return null;
} finally {
result2.append("world");
System.out.println("execute testFinally2");
}
}
public static void main(String[] args) {
int test1 = testFinally1();
System.out.println(test1);
StringBuffer test2 = testFinally2();
System.out.println(test2);
}
}

运行结果:

1
2
3
4
execute testFinally1
1
execute testFinally2
helloworld

程序在执行到return时会先将返回值存储在一个指定位置,其次去执行finally块,最会再return。

在finally块中改变基本类型的数据result1/引用类型数据result2的值,与java的值传递和引用传递相关。值传递中,形参和实参有着不同的存储单元,对形参的改变不会影响实参的值;引用传递中,传递的是对象的地址,形参和实参的对象指向同一块存储单元对形参的改变就会影响实参的值。

二、如果执行finally代码块之前方法返回了结果,或者JVM退出了,finally块中的代码还会执行吗?finally不会执行的情况

  • java程序中的 finally 块并不一定会被执行。
    至少有两种情况 finally语句是不会执行的。

(1)try语句没有被执行到。

即没有进入try代码块,对应的finally自然不会执行。

比如,在try语句之前return就返回了,这样finally不会执行;
或者在程序进入java之前就出现异常,会直接结束,也不会执行finally块。

(2)在try/catch块中有System.exit(0)来退出JVM。

System.exit(0)是终止 JVM的 (0 代表正常退出,非零代表异常退出),会强制退出程序,finally{} 中的代码就不会被执行。

参考资料: