java异常—— finally 子句+带资源的 try语句
【0】README
0.1) 本文描述+源代碼均 轉自 core java volume 1, 旨在理解 java異常—— finally 子句+帶資源的 try語句 的相關知識;
【1】 finally 子句相關
1.1)產生資源回收問題:當代碼拋出一個異常時, 就會終止方法中剩余代碼的處理, 并退出這個方法的執行。如果方法獲得了一些本地資源,且只有這個方法知道, 那么就會產生資源回收問題;
1.2)解決方法:
- 1.2.1)一種解決方法是 捕獲并重新拋出所有異常: 但是, 這種方法比較乏味, 因為需要在兩個地方取出所有分配的資源;
- 1.2.2)一種更好的解決方法是 finally 子句;
1.3)看個荔枝(不管是否異常被捕獲, finally子句都會被執行),在下面的示例中, 程序將在所有cases 下關閉文件:
InputStream in = new FileIinputStream(); try { //1 code that might throw exceptions //2 } catch(IOException e) { //3 show error msg //4 } finally {// 5in.close(); } //6對以上代碼的分析(Analysis)(在上面的 代碼中, 有下列3種cases 會執行finally 子句):
A1)代碼沒有拋出異常。在這種情況下, 程序首先執行try語句塊中的全部代碼, 然后執行 finally子句中的代碼。隨后執行try語句塊之后的 第一條語句, 執行順序為1、2、5、6;
A2)拋出一個在catch 子句中捕獲的異常。
- A2.1)如果catch子句沒有拋出異常, 程序將執行try 語句塊之后的第一條語句, 在這里的執行順序為 1、3、4、5、6;
- A2.2)如果catch 子句拋出異常, 異常將被拋出這個方法的調用者, 在這里, 執行順序為 1、3、5;
- A3)代碼拋出了一個異常, 但catch 子句無法捕獲; 在這里, 執行順序為 1、5;
1.4)try語句可以只有 finally子句,而沒有catch子句:如,
InputStream in = "..."; try {} finally {in.close(); }- 1.4.1)無論在try 語句塊中是否遇到異常,finally子句中的 in.close() 語句都會被執行, 當然, 如果真的遇到一個異常, 這個異常將會被重新拋出, 并且必須由另一個catch 子句捕獲;
- 1.4.2)我們在需要關閉資源的時候, 用這種方式使用 finally 子句是一個不錯 的選擇;
Hint)這里, 強烈建議獨立使用 try/catch 和 try/finally 語句塊, 可以提高代碼的清晰度。如,(強烈推薦-strongly recommended)
InputStream in = "..."; try {try{code that might throw exceptions} finaly{in.close();} } catch(IOException e) {show error msg }- H1)內層的try語句塊有一個職責, 就是確保關閉輸入流;
- H2)外層的try 語句塊也只有一個職責, 就是確保報告出現的錯誤;
- H3)這種設計不僅清楚, 而且還將報告finally子句中出現的錯誤;
Warning)
- W1)當finally子句包含 return 語句時, 將會出現一種意想不到的結果;
- W2)假設利用return 語句從try 語句塊中退出。 在這個方法返回前, finally子句的內容將被執行;
1.5)如果finally子句也有一個 return, 這個返回值將會覆蓋原始的返回, 看個荔枝
public static int f(int n) {try{int r = n * n;return r;}finally{if(n==2) return 0;} }對上述代碼的分析(Analysis):如果調用 f(2),那么try語句塊return 4, 而方法返回前, 還要執行 finally子句, 其返回0, 這個返回值會覆蓋掉原始的返回值4**(即最終的返回值是0 而不是4);**
1.6)出現的問題:
InputStream in = "..."; try {code that might throw exceptions } finally {in.close(); }- 1.6.1)問題描述:對于上述代碼, 假設在 try 語句塊中的代碼拋出了 IOException異常, 這些異常只有這個方法的調用者才能夠處理。 執行finally語句塊, 并調用close 方法。 而 close 方法本身也可能拋出 IOException異常。 當出現這種case 時, 原始的異常數據將丟失, 轉而拋出 close 方法的異常;
- 1.6.2)解決方法: 如果你想做適當處理的話, 重新拋出原來的異常,代碼會變得極其繁瑣;如下圖所示:
【2】 帶資源的 try語句
2.1)對于以下代碼模式:
open a resource try {work with the resource } finally {close the resource }- 2.1.1)假設資源屬于一個實現了 AutoCloseable 接口的類, AutoCloseable 接口有一個方法:
Annotation)還有一個 Closeable 接口, 它是 AutoCloseable 的子接口, 也包含一個 close方法, 不過, 這個方法聲明為拋出一個 IOException;
2.2)帶資源的 try語句(try-with-resource)的最簡單形式為:
- 2.2.1)try塊退出時, 會自動調用 res.close()。看個荔枝——讀取一個文件中的所有單詞:
- 上述代碼中的 try塊正常退出時, 或者存在一個異常時, 都會調用 in.close()方法, 就好像使用了 finally塊一樣;
- 2.2.2)還可以指定多個 資源:
- 2.2.3)無論這個塊如何退出, in 和 out 都會關閉: 如果你使用常規方式手動編程,就需要兩個嵌套的 try/finally 子句;
Conclusion)
- C1)我們看到, 如果try塊中拋出一個異常, 而且close方法也拋出一個異常, 這就會帶來一個難題, 現在 帶資源的try塊解決了這個問題;
- C2)原來的異常會被重新拋出, 而 close方法拋出的異常會“被抑制”;
- C3)這些異常將自動捕獲, 并由 addSuppressed 方法增加到原來的異常。如果對異常有興趣, 可以調用 getSuppressed 方法, 它會得到從 close方法 拋出并被抑制的異常列表;
Attention)只要需要關閉資源, 就要盡可能地使用帶資源的 try語句;
總結
以上是生活随笔為你收集整理的java异常—— finally 子句+带资源的 try语句的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 摩托罗拉手机a1200(摩托罗拉手机A1
- 下一篇: 多空线设置(什么是多空线)