finally与return执行的时机

finally不一定执行的情况

  1. JVM退出, 即在try catch中有System.exit()
  2. 在执行try catch时线程中断

finally一定执行的情况(以下说法并不准确, 只是为了方便理解, 还需要去了解生成的字节码是怎么样的才行)

  1. 首先要将try catch当做一个整体, 当try catch中有return语句时, 则该整体有一个返回值, 当没有return语句时, 该整体没有返回值。这里try catch类似于一个函数 , 函数可以有返回值,也可以没有返回值
  2. finally执行的时机:finally可以看作是一个subroutine,在try catch退出前, 即如果当try catch当做一个函数的话, 就是在该函数退出前,执行的,try catch中的变量是作为finally这个subroutine的参数复制了一份,传给了finally。
  3. finally执行的行为:finally是做为一个subroutine进行执行的, 所以, 如果finally中修改了try catch中的变量, 那么修改的是一个副本(注意基本类型与引用的不同)
  4. return的时机有三种, 一是在try catch中return, 二是在finally中return, 三是在try catch finally外返回。 对于一,因为finally中修改的是副本, 所以,不影响返回值(对于引用还是影响的),且该返回值做为整个函数的返回值, 对于二, finally的返回值作为整个函数的返回值, 所以如果try catch和finally中都有return , 则finally中的会覆盖try catch的, 对于三, try catch中和finally都没有return , 如果try catch finally都修改了某一个变量, 那么因为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
//返回4
public static int getValue() {
int i = 1;
try {
i = 4;
return i;
} finally{
i++;
}
}

//返回5
public static int getValue() {
int i = 1;
try {
i = 4;

} finally{
i++;
return i;
}
}

//返回5
public static int getValue() {
int i = 1;
try {
i = 4;
} finally{
i++;
}
return i;
}

以上用法只是为了说明finally与return的关系, finally最大的作用是用来做资源回收(C++中析构函数工作的一部分)

更多例子与解释

后记

其实也不需要对finally对return的影响那么了解。最关键的是了解使用finally的目的是什么,要有正确的实践。而有些例子则是很不好的实践, 应该尽量避免(这使得代码很不容易理解)

使用finally的主要目的是回收,关闭资源, 并不是让其返回某个值的。

同时, 在try语句中, 尽量不要使用System.exit()这样会导致finally中的语句不被执行