结论:
1、不管有木有出现异常,finally块中代码都会执行;
2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,不管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
分析:
引用别人的总结,总结的不错,但是why?学知识不可不求甚解,那就来分析一下
<em>public static Integer testTryCatchFinally () {
Integer result;
try {
result = 10/0;
return result;
}catch (Exception e) {
result = 2;
return result;
}finally {
result = 3;
// return result;
}
}</em>
编译后的字节码指令
public static java.lang.Integer testTryCatchFinally();
0 bipush 10 //将单字节的常量值10推送至栈顶
2 iconst_0 //将int型0推送至栈顶
3 idiv //将栈顶两int型数值相除并将结果压入栈顶
4 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [122] //调用静态方法
7 astore_0 [result] // 将栈顶引用型数值存入第一个本地变量
8 aload_0 [result] //将第一个引用类型本地变量推送至栈顶
9 astore_3 //将栈顶应用型数值存入第四个本地变量
10 iconst_3 //将int型3推送至栈顶
11 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [122] //调用静态方法
14 astore_0 [result] // 将栈顶引用型数值存入第一个本地变量
15 aload_3 //将第四个引用类型本地变量推送至栈顶
16 areturn //从当前方法返回对象引用
17 astore_1 [e] // 将栈顶引用型数值存入第二个本地变量
18 iconst_2 //将int型2推送至栈顶
19 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [122] //调用静态方法
22 astore_0 [result] // 将栈顶引用型数值存入第一个本地变量
23 aload_0 [result] //将第一个引用类型本地变量推送至栈顶
24 astore_3 // 将栈顶引用型数值存入第四个本地变量
25 iconst_3 //将int型3推送至栈顶
26 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [122] //调用静态方法
29 astore_0 [result] // 将栈顶引用型数值存入第一个本地变量
30 aload_3 //将第四个引用类型本地变量推送至栈顶
31 areturn //从当前方法返回对象引用
32 astore_2
33 iconst_3
34 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [122]
37 astore_0 [result]
38 aload_2
39 athrow //将栈顶的异常抛出
Exception Table:
[pc: 0, pc: 10] -> 17 when : java.lang.Exception
[pc: 0, pc: 10] -> 32 when : any
[pc: 17, pc: 25] -> 32 when : any
Line numbers:
[pc: 0, line: 42]
[pc: 8, line: 43]
[pc: 10, line: 48]
[pc: 15, line: 43]
[pc: 17, line: 44]
[pc: 18, line: 45]
[pc: 23, line: 46]
[pc: 25, line: 48]
[pc: 30, line: 46]
[pc: 32, line: 47]
[pc: 33, line: 48]
[pc: 38, line: 50]
Local variable table:
[pc: 8, pc: 17] local: result index: 0 type: java.lang.Integer
[pc: 23, pc: 32] local: result index: 0 type: java.lang.Integer
[pc: 38, pc: 40] local: result index: 0 type: java.lang.Integer
[pc: 18, pc: 32] local: e index: 1 type: java.lang.Exception
Stack map table: number of frames 2
[pc: 17, same_locals_1_stack_item, stack: {java.lang.Exception}]
[pc: 32, same_locals_1_stack_item, stack: {java.lang.Throwable}]
分析字节码指令:
逐一分析
1、不管有木有出现异常,finally块中代码都会执行;
观察字节码指令发现,finally字节码指令已经编译到try/catch代码块里
2、当try和catch中有return时,finally仍然会执行;
观察字节码指令发现,finally字节码指令已经编译到try/catch代码块里,并且return指令是在最后
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
上图分析得知,最终load下标为3的变量到栈顶并返回,而不是返回finally的result=3,正常情况返回try块里的result计算结果x,异常返回catch块里的result=2
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
分析一下指令,finally中有return,try/catch块中编译后无return指令,失效,只返回finally块中的result=3,而不是程序提前退出。
<em> public static java.lang.Integer testTryCatchFinally();
0 bipush 10
2 iconst_0
3 idiv
4 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [122]
7 astore_0 [result]
8 goto 21
11 astore_1 [e]
12 iconst_2
13 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [122]
16 astore_0 [result]
17 goto 21
20 pop
21 iconst_3
22 invokestatic java.lang.Integer.valueOf(int) : java.lang.Integer [122]
25 astore_0 [result]
26 aload_0 [result]
27 areturn
Exception Table:
[pc: 0, pc: 11] -> 11 when : java.lang.Exception
[pc: 0, pc: 20] -> 20 when : any
Line numbers:
[pc: 0, line: 42]
[pc: 8, line: 43]
[pc: 11, line: 44]
[pc: 12, line: 45]
[pc: 17, line: 46]
[pc: 20, line: 47]
[pc: 21, line: 48]
[pc: 26, line: 49]
Local variable table:
[pc: 8, pc: 11] local: result index: 0 type: java.lang.Integer
[pc: 17, pc: 20] local: result index: 0 type: java.lang.Integer
[pc: 26, pc: 28] local: result index: 0 type: java.lang.Integer
[pc: 12, pc: 20] local: e index: 1 type: java.lang.Exception
Stack map table: number of frames 3
[pc: 11, same_locals_1_stack_item, stack: {java.lang.Exception}]
[pc: 20, same_locals_1_stack_item, stack: {java.lang.Throwable}]
[pc: 21, same]</em>