首頁 >Java >java教程 >Java中finally與return的執行順序解析(程式碼範例)

Java中finally與return的執行順序解析(程式碼範例)

不言
不言原創
2018-09-11 14:16:021734瀏覽

這篇文章帶給大家的內容是關於Java中finally與return的執行順序解析(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

都知道,finally的執行特點

##1、不管有木有出現異常,finally區塊中程式碼都會執行;

2、當try和catch中有return時,finally仍然會執行。

那麼問題來了,執行順序是怎麼樣的呢?

一個簡單的測試類別及反編譯後的字節碼:

public class Test {
         publicstatic void main(String[] args) {
             System.out.println(test());
         }
 
         publicstatic int test() {
                   try{
                            System.out.println("Codesin try block.");
                            return0;
                   }catch (Exception e) {
                            System.out.println("Codesin catch block.");
                            return100;
                   }finally {
                            System.err.println("Codesin finally block.");
                   }
         }
}
/*
 public static int test();
   Code:
      0: getstatic     #2                  // Fieldjava/lang/System.out:Ljava/io/PrintStream;
      3: ldc           #5                  // String Codes in try block.
      5: invokevirtual #6                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      8: iconst_0
      9: istore_0
     10: getstatic     #7                  // Field java/lang/System.err:Ljava/io/PrintStream;
     13: ldc           #8                  // String Codes in finallyblock.
     15: invokevirtual #6                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     18: iload_0
     19: ireturn
     20: astore_0
     21: getstatic     #2                  // Fieldjava/lang/System.out:Ljava/io/PrintStream;
     24: ldc           #10                 // String Codes in catchblock.
     26: invokevirtual #6                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     29: bipush        100
     31: istore_1
     32: getstatic     #7                  // Fieldjava/lang/System.err:Ljava/io/PrintStream;
     35: ldc           #8                  // String Codes in finallyblock.
     37: invokevirtual #6                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     40: iload_1
     41: ireturn
     42: astore_2
     43: getstatic     #7                  // Fieldjava/lang/System.err:Ljava/io/PrintStream;
     46: ldc           #8                  // String Codes in finallyblock.
     48: invokevirtual #6                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     51: aload_2
     52: athrow
*/

可以將我們寫的程式碼和編譯後的字節碼做一下比較:

Java中finally與return的執行順序解析(程式碼範例)

發現虛擬機器為我們做了很多事,它將finally語句區塊插到try,catch與return語句之間了。這也就是為什麼無論異常與否,回傳與否,finally都會執行的原因。既然,finally都會執行,那麼在finally中return什麼就是什麼。既然finally前面所有return都是無效的,return還有什麼意義呢,所以,實際中finally區塊是不被允許回傳的。 eclipse編譯器會提示warning:finallyblock does not complete normally。

幾個情形的測試程式碼

try{ return; }catch(){} finally{} return;

測試程式碼:

1.基本資料型別

   public static int test1(){
      int a = 10;
      try{
         a = 20;
         return a;
      }catch(Exception e){
         //other codes.
      }finally{
         a += 5;
         //other codes.
      }
      return a;
   }//最终返回值为20

2.引用資料型別改變引用物件的值

   public static StringBuffer test2(){
      StringBuffer sb = new StringBuffer("abc");
      try{
         return sb;
      }catch(Exception e){
         //other codes.
      }finally{
         sb.append("DEF");
         //other codes.
      }
      return sb;
   }//最终返回中内容为abcDEF
  public static StringBuffer test3(){
      StringBuffer sb = new StringBuffer("abc");
      try{
         return sb;
      }catch(Exception e){
         //other codes.
      }finally{
         sb = new StringBuffer("DEF");
         //other codes.
      }
      return sb;
   }//最终返回值中的内容为abc

在此種情形的測試中可以發現,在finally之前若有return語句,finally對返回變數無論做什麼修改,變數本身是不會再變的,例如為基本類型的變數重新賦值,或是為引用類型的變數重新指定引用都是不會記錄到傳回值中的。但是finally中的語句會執行,那麼在finally中對引用類型的變數所指向的物件內容是可以修改的,且修改有效。此種情形可以這樣理解,遇到return語句,虛擬機器為return的值蓋了一間房子,房子能隨便拆嗎?不能。但是房子裡面的人是可以改變的。基本資料型別和引用型別的變數本身就是房子,引用型別變數指向的物件中的內容就是房子裡的人。

有這樣一個小測試:

   public static int test(int num){
      int a = 10;
      try{
         return a;
      }catch(ArithmeticException e){
         a = 20;
         return a;
      }finally{
         a = 30;
         return a;
      }
   }

1.1 try 區塊中沒有異常時回傳值是多少?

1.2 try區塊中有ArithmeticException異常時回傳值是多少?

1.3 try區塊中有其他異常時回傳值是多少?

答案:全部是30.原因是在執行完try區塊中return之前的程式碼後,jvm在return之間插入了finally區塊中的程式碼,finally區塊中含有return,那麼就直接回傳了。

相關推薦:

Java中try與finally以及return語句的執行順序

舉例說明Java中程式碼區塊的執行順序

以上是Java中finally與return的執行順序解析(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn