
最近在整理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邏輯。