java finally深入探究

來源:互聯網
上載者:User

標籤:hat   put   實現   輸出資料流   位元組   out   本地變數   相關   post   

When---什麼時候需要finally:

在jdk1.7之前,所有涉及到I/O的相關操作,我們都會用到finally,以保證流在最後的正常關閉。jdk1.7之後,雖然所有實現Closable介面的流,可以通過在try塊中定義,從而實現jvm自動關閉輸入輸出資料流。但其實在我們需要在代碼塊返回之前,實現在不管前面的操作是否執行成功,都要執行的某操作A。這時候我們就可以將A放入finally塊中。很常見的一個操作就是鎖的unlock操作。

 

What---什麼是finally:

字面解釋就是最終,eventually。其作用就是保證在try塊中的代碼執行完成之後,必然會執行finally中的語句。不管try塊中是否拋出異常。

 

How---如何使用finally:

finally塊必須配合try塊使用,而不能單獨使用。

 

Deeper---深入探究finally塊:

在深入探究之前我們直接先給出四個結論:

1. finally塊只會在try塊執行的情況下才執行

2. finally塊在離開try塊執行完成後或者try塊未執行完成但是接下來是控制轉移語句時(return/continue/break)在控制轉移語句之前執行。

3. 在執行finally語句之前,控制轉移語句會將傳回值存在本地變數中

4. finally塊中的控制轉移return語句能夠覆蓋try或者catch塊中的傳回值

其中1、2不做進一步說明。我們來對3和4直接通過兩個例子進行深入理解:

關於3的例子:

 1 public static void main(String[] args) { 2     System.out.println("return " + testFinally()); 3 } 4  5 public static String testFinally() { 6     int i = 10; 7     try { 8         return i + ""; 9     } finally {10         i++;    // 即使i的值改變,但是return語句涉及到的i的值已經儲存在本地變數中11     }12 }13 14 // 輸出是10.

我們直接分析位元組碼得:

 1  public static java.lang.String testFinally(); 2     descriptor: ()Ljava/lang/String; 3     flags: ACC_PUBLIC, ACC_STATIC 4     Code: 5       stack=3, locals=3, args_size=0 6          0: bipush        10           --將10壓入棧中 7          2: istore_0                --將棧頂元素(10)儲存到局部變數0中 8          3: new           #22                 // class java/lang/StringBuilder 9          6: dup10          7: iload_0                --從局部變數0中裝載資料(10)入棧,後續代碼是用來進行字串拼接11          8: invokestatic  #47                 // Method java/lang/String.valueOf:(I)Ljava/lang/String;12         11: invokespecial #26                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V13         14: invokevirtual #37                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;14         17: astore_2               --拼接後的結果存入局部變數2中(是10+"")15         18: iinc          0, 1         --局部變數0的值加116         21: aload_2                --從局部變數2中裝載資料(為10+"")17         22: areturn                --返回結果18         23: astore_1               --將前面變數0加1的結果存入局部變數119         24: iinc          0, 1         --將局部變數0加120         27: aload_1                --裝載局部變數1的值21         28: athrow

其實areturn返回的是變數的引用值。這意味著,如果最終返回的是物件類型。那麼在finally塊執行之前,儲存在本地變數中的只是對象引用的值,而不是對象的深拷貝。我們可以在finally塊中對返回對象的屬性進行改變。直接看下一個例子:

 1 public static void main(String[] args) { 2     System.out.println("return " + testFinally()); 3 } 4  5 public static Map<String, String> testFinally() { 6     Map<String, String> map = new HashMap<String, String>(); 7     try { 8         map.put("aaa", "aaa"); 9         return map;10     } finally {11         map.put("aaa", "bbb");12         map = null;13     }14 }15 16 // 輸出為:return {aaa=bbb}

下面我們再來說說關於第4點的例子:

 1 public static void main(String[] args) { 2     System.out.println("return " + testFinally()); 3 } 4  5 private static String testFinally() { 6     try { 7         return "456"; 8     } finally { 9         return "123";10     }11 }12 13 // 輸出:123
 1 public static void main(String[] args) { 2     System.out.println("return " + testFinally()); 3 } 4  5 private static String testFinally() { 6     try { 7         throw new SQLException(); 8         //return "456"; 9     } catch (SQLException e) {10         System.out.println("catch SQLException!");11         throw new RuntimeException("123");12     }13     finally {14         return "123";15     }16 }17 18 // 輸出為:19 catch SQLException!20 return 123

更多的其他例子:

 1 public static int getValue() { 2     int i = 1; 3     try { 4         i = 4; 5     } finally { 6         i++; 7         return i; 8     } 9 }10 // 最終返回511 12 public static int getValue() {13     int i = 1;14     try {15         i = 4;16     } finally {17         i++;18     }19 20     return i;21 }22 // 最終返回523 24 public static void main(String[] args) {25     System.out.println(test());26 }27 public static String test() {28     try {29         System.out.println("try block");30         return test1();31     } finally {32         System.out.println("finally block");33     }34 }35 public static String test1() {36     System.out.println("return statement");37     return "after return";38 }39 // 最終輸出:40 try block41 return statement42 finally block43 after return

 

參考連結:

https://www.ibm.com/developerworks/cn/java/j-lo-finally/

http://www.cnblogs.com/lanxuezaipiao/p/3440471.html

http://blog.csdn.net/michealmc/article/details/52237639

 

java finally深入探究

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.