try中有return语句,finally还会执行吗?
先说结论,是可以执行的
我们来看看实际的实验结果
实验一
假设我们有这样一个代码块:
int x = 1;
try {
++x;
return x;
} catch (Exception e){
e.printStackTrace();
}finally {
System.out.println(x);
}
System.out.println(x);
return x;
你们认为会执行打印语句么?
没错,这个代码块是会执行finally里面的打印语句的,结果就如下所示:
实验二
现在我们稍微改改上面的代码
int x = 1;
try {
++x;
return x;
} catch (Exception e){
e.printStackTrace();
}finally {
x = 3
}
return x;
-----------------------------------------
//这里是在返回后的主函数内打印
System.out.println(x);
现在我们不在finally里面打印,而是返回到主函数后再打印,那么结果是是什么呢?
我想应该有很多读者和我最初的想法一样:“既然finally语句会执行,那么最后返回的x值当然是3了呀!”如果是这样的想法,那么恭喜你,你也回答错了,其实这段代码打印的结果是2
为什么返回到主程序的值会是2呢?其实在JVM规范里面明确说明了这种情况:
If the
try
clause executes a return, the compiled code does the following:
- Saves the return value (if any) in a local variable.
- Executes a jsr to the code for the
finally
clause.- Upon return from the
finally
clause, returns the value saved in the local variable.
也就是说,try中有return的时候的执行顺序大概如下:
1、先把要return的x值保存下来
2、执行finally语句块内的代码
3、返回第一步保存下来的x值
这么一看,也就清晰明白了为什么上面的返回值为2
还有一种特别的情况,假设finally语句块内又有一个return语句:
int x = 1;
try {
++x;
return x;
} catch (Exception e){
e.printStackTrace();
}finally {
x = 3;
return x;
}
-----------------------------------------
//这里是在返回后的主函数内打印
System.out.println(x);
那么此时的结果又是什么呢?
可以看到,此时的打印结果返回了3,也就是说,真正的返回语句是finally语句块内的return,前面try语句块中的return被丢弃了。
小结
从上面的实验来看,可以得到相关的结论为:
- try中有return, 会先将值暂存,无论finally语句中对该值做什么处理,最终返回的都是try语句中的暂存值。
- 当try与finally语句中均有return语句,会忽略try中return,真正的返回值为finally里面的return。