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

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

不言
發布: 2018-09-11 14:16:02
原創
1898 人瀏覽過

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

都知道,finally的執行特點

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

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

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.基本資料型別

1

2

3

4

5

6

7

8

9

10

11

12

13

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.引用資料型別改變引用物件的值

1

2

3

4

5

6

7

8

9

10

11

12

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

登入後複製

1

2

3

4

5

6

7

8

9

10

11

12

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的值蓋了一間房子,房子能隨便拆嗎?不能。但是房子裡面的人是可以改變的。基本資料型別和引用型別的變數本身就是房子,引用型別變數指向的物件中的內容就是房子裡的人。

有這樣一個小測試:

1

2

3

4

5

6

7

8

9

10

11

12

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
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板