天天看點

其實return和finally的執行順序問題非常簡單,你隻有看看代碼的指令就清楚咯return和finally的順序問題

其實return和finally的執行順序問題非常簡單,你隻有看看代碼的指令就清楚咯return和finally的順序問題

  最近在整理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,就會建立一個棧幀(存儲局部變量表,操作數棧等資訊)進入虛拟機棧。每一個方法從調用到執行完畢,就是一個棧幀從虛拟機棧中入棧到出棧的過程。對應的棧幀情況為

其實return和finally的執行順序問題非常簡單,你隻有看看代碼的指令就清楚咯return和finally的順序問題

ldc:将int,float或者String類型常量從常量池推送至棧頂。

astore:将棧頂引用型類型資料存入指定本地變量。

aload:将制定的引用類型變量推送至棧頂

檢視關鍵的指令為:

其實return和finally的執行順序問題非常簡單,你隻有看看代碼的指令就清楚咯return和finally的順序問題

還有一種情況需要注意,如果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 對應的棧幀位置
        }
    }
}      
其實return和finally的執行順序問題非常簡單,你隻有看看代碼的指令就清楚咯return和finally的順序問題

  通過指令我們可以看到在finally中的return關鍵字的指令傳回的就是finally中的局部變量的資訊,可以了解為finally中的return會覆寫掉try塊中的return邏輯。