最近在整理Java常见的面试题,刚好整理到return和finally的执行顺序问题,这个很多小伙伴比较困惑,所以波波老师就通过指令带大家彻底弄清楚下
return和finally的顺序问题
分析如下的代码程序,给出输出结果,并给出原因
public class Demo02 { public static void main(String[] args) { Demo02 demo02 = new Demo02(); System.out.println(demo02.getName("bobo")); } public String getName(String name){ String res = ""; try { res = name; return res; }finally { res = "波波烤鸭"; } } }
输出的结果是:bobo
原因:通过指令分析我们可以发现在 return 代码执行的时候会将局部变量保存在 栈帧的顶部,然后在finally中修改的还是原来的栈帧位置的局部变量,最终返回的信息还是栈帧顶部的变量,所以finally代码块在return关键字之后会执行,但是不会改变栈帧顶部的信息。
指令分析:
首先我们要清楚在jvm中,每个线程都具有自己的虚拟机栈。当执行方法时,如上面的getName,就会创建一个栈帧(存储局部变量表,操作数栈等信息)进入虚拟机栈。每一个方法从调用到执行完毕,就是一个栈帧从虚拟机栈中入栈到出栈的过程。对应的栈帧情况为
ldc:将int,float或者String类型常量从常量池推送至栈顶。
astore:将栈顶引用型类型数据存入指定本地变量。
aload:将制定的引用类型变量推送至栈顶
查看关键的指令为:
还有一种情况需要注意,如果finally和try块中都有return关键字会怎么样呢?
public class Demo02 { public static void main(String[] args) { Demo02 demo02 = new Demo02(); System.out.println(demo02.getName("bobo")); } public String getName(String name){ String res = ""; try { res = name; return res; }finally { res = "波波烤鸭"; return res; // 指令中返回的就不是栈帧顶部的数据了 而是 res 对应的栈帧位置 } } }
通过指令我们可以看到在finally中的return关键字的指令返回的就是finally中的局部变量的信息,可以理解为finally中的return会覆盖掉try块中的return逻辑。