Try-Catch-Finally語句塊執行問題


Try-Catch-Finally語句塊執行問題

記錄一個今天某公司的面試問題,其實我問題回答對了,但是面試官問我動手驗證過沒有,這還真沒有,純理論,被懟慘了,希望自己能變得更強大。

 

Try-Catch-Finally語句塊執行問題。

一起來看下面這串代碼:

public class TryCatchFinally { public static void main(String[] args){ System.out.println(get()); } private static int get(){ try{ System.out.println("Try語句塊"); return 0; }catch (Exception e){ System.out.println("Catch語句塊"); return 1; }finally { System.out.println("Finally語句塊"); return 2; } } }

程序運行結果:

 

 

 

 

再來看下面這串代碼:

public class TryCatchFinally { public static void main(String[] args){ System.out.println(get()); } private static int get(){ try{ System.out.println("Try語句塊"); throw new Exception(); }catch (Exception e){ System.out.println("Catch語句塊"); return 1; }finally { System.out.println("Finally語句塊"); return 2; } } }

 

程序運行結果:

 

 

 

總結:

通過上面兩個例子可以看出:

  • 無論是否在 try 語句塊中拋出異常,finally語句塊中的內容都會得到執行。
  • 只有 try 語句塊中拋出異常了,catch語句塊中的內容才會得到執行。
  • 但無論在 try 和 catch 語句塊中是否有返回語句,finally 語句都會得到執行,並且當 finally 語句中有 return 語句,try 和 catch 語句中的 return 語句都無法得到執行。

 

當然去掉 finally 中的 return 語句,try 或 catch 中的 return 語句又可以得到執行,這個可以直接在上面那個程序進行試驗。

同時 finally 語句塊中包含 return 語句,編譯器也會給出警告:finally block can not complete normally。

這是因為 finally 的 return 語句覆蓋了前面的 return 語句,是一種不合理的做法,盡量不要在 finally 中使用 return。

 

補充一點:

為什么 finally 語句始終都會得到執行,這里推薦一篇博客:https://blog.csdn.net/neosmith/article/details/48093427

簡單來說就是 JVM 將 finally 語句塊中的東西都復制了一遍到 try 和 catch 語句塊中,確保 finally語句塊必定會得到執行。

 

 

 

 

補充(2019/9/22)

 

今天又發現一個問題,來更新一下,看下面這串代碼:

 

public class TestMain {
    public int test(){
        int a=0;
        try{
            a++;
            throw new Exception("故意的");
        }catch (Exception e){
            a++;
            return a;
        }finally {
            a++;
            System.out.println("a1="+a);
        }
    }
    public static void main(String[] args){
        int a=new TestMain().test();
        System.out.println("a2="+a);
    }
}

 

 

 

可以看到這個地方在test中打印的a值為 3 ,但返回值卻是 2 ,這個地方又難住了,特地查了一下資料,有這么一句話:

“Java 虛擬機會把 finally 語句塊作為 subroutine直接插入到 try 語句塊或者 catch 語句塊的控制轉移語句之前。但是,還有另外一個不可忽視的因素,那就是在執行 subroutine之前,try 或者 catch 語句塊會保留其返回值到本地變量表中。待 subroutine 執行完畢之后,再恢復保留的返回值到操作數棧中,然后通過 return 或者 throw 語句將其返回給該方法的調用者。”

 

也就是說這里是在 a++ 和 return 之間插入了 finally語句塊,但是在執行 finally 語句塊之前,先對 a 的值進行了保存,而之后的 finally語句塊中對 a 進行的修改只是一個值傳遞,並沒有對變量表中的 a 的值進行修改,所以也就是為什么在 finally 中 a 值為 3,而返回值 a 卻為 2。

當然這里如果將 a 改成一個對象,對對象中的某個值進行修改,也就是進行引用傳遞,則會對返回值進行修改。

這里推薦一篇博客:https://www.jianshu.com/p/011062aaa855

 

 

 

 

 2019/9/22日更新

 

 

吾生也有涯,而知也無涯。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM