日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java异常—— finally 子句+带资源的 try语句

發布時間:2023/12/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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)解決方法: 如果你想做適當處理的話, 重新拋出原來的異常,代碼會變得極其繁瑣;如下圖所示:
InputStream in = "..."; Exception ex = null; try {try{code that might throw exceptions} catch(Exception e){ex = e;throw e;} } finaly {try{in.close();}catch(Exception e){if(ex == null) throw e;} }

【2】 帶資源的 try語句

2.1)對于以下代碼模式:

open a resource try {work with the resource } finally {close the resource }
  • 2.1.1)假設資源屬于一個實現了 AutoCloseable 接口的類, AutoCloseable 接口有一個方法:
void close() throws Exception;

Annotation)還有一個 Closeable 接口, 它是 AutoCloseable 的子接口, 也包含一個 close方法, 不過, 這個方法聲明為拋出一個 IOException;
2.2)帶資源的 try語句(try-with-resource)的最簡單形式為:

try(Resource res) {work with res }
  • 2.2.1)try塊退出時, 會自動調用 res.close()。看個荔枝——讀取一個文件中的所有單詞:
try(Scanner in = new Scanner(new FileInputStream("/usr/.../"))) {while(in.hasNext())System.out.println(in.next()); }
  • 上述代碼中的 try塊正常退出時, 或者存在一個異常時, 都會調用 in.close()方法, 就好像使用了 finally塊一樣;
  • 2.2.2)還可以指定多個 資源:
try(Scanner in = new Scanner(new FileInputStream("/usr/.../")), PrintWriter out = new PrintWriter("out.txt")) {while(in.hasNext())out.println(in.next().toUpperCase()); }
  • 2.2.3)無論這個塊如何退出, in 和 out 都會關閉: 如果你使用常規方式手動編程,就需要兩個嵌套的 try/finally 子句;

Conclusion)

  • C1)我們看到, 如果try塊中拋出一個異常, 而且close方法也拋出一個異常, 這就會帶來一個難題, 現在 帶資源的try塊解決了這個問題;
  • C2)原來的異常會被重新拋出, 而 close方法拋出的異常會“被抑制”;
  • C3)這些異常將自動捕獲, 并由 addSuppressed 方法增加到原來的異常。如果對異常有興趣, 可以調用 getSuppressed 方法, 它會得到從 close方法 拋出并被抑制的異常列表;

Attention)只要需要關閉資源, 就要盡可能地使用帶資源的 try語句;

總結

以上是生活随笔為你收集整理的java异常—— finally 子句+带资源的 try语句的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。