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

來源:互聯網
上載者:User
本篇文章給大家帶來的內容是關於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*/

可以將我們編寫的代碼和編譯後的位元組碼做一下對比:

發現虛擬機器為我們做了好多事,它將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.基礎資料型別 (Elementary Data Type)

   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的值蓋了一套房子,房子能隨便拆嗎?不能。但是房子裡面的人是可以變的。基礎資料型別 (Elementary Data Type)和參考型別的變數本身就是房子,參考型別變數指向的對象中的內容就是房子中的人。

有這樣一個小測試:

   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,那麼就直接返回了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.