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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java异常—— finally 子句+带资源的 try语句 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【0】README

0.1) 本文描述+源代碼均 轉(zhuǎn)自 core java volume 1, 旨在理解 java異常—— finally 子句+帶資源的 try語(yǔ)句 的相關(guān)知識(shí);


【1】 finally 子句相關(guān)

1.1)產(chǎn)生資源回收問(wèn)題:當(dāng)代碼拋出一個(gè)異常時(shí), 就會(huì)終止方法中剩余代碼的處理, 并退出這個(gè)方法的執(zhí)行。如果方法獲得了一些本地資源,且只有這個(gè)方法知道, 那么就會(huì)產(chǎn)生資源回收問(wèn)題;
1.2)解決方法:

  • 1.2.1)一種解決方法是 捕獲并重新拋出所有異常: 但是, 這種方法比較乏味, 因?yàn)樾枰趦蓚€(gè)地方取出所有分配的資源;
  • 1.2.2)一種更好的解決方法是 finally 子句;

1.3)看個(gè)荔枝(不管是否異常被捕獲, finally子句都會(huì)被執(zhí)行),在下面的示例中, 程序?qū)⒃谒衏ases 下關(guān)閉文件:

InputStream in = new FileIinputStream(); try { //1 code that might throw exceptions //2 } catch(IOException e) { //3 show error msg //4 } finally {// 5in.close(); } //6

對(duì)以上代碼的分析(Analysis)(在上面的 代碼中, 有下列3種cases 會(huì)執(zhí)行finally 子句):

  • A1)代碼沒(méi)有拋出異常。在這種情況下, 程序首先執(zhí)行try語(yǔ)句塊中的全部代碼, 然后執(zhí)行 finally子句中的代碼。隨后執(zhí)行try語(yǔ)句塊之后的 第一條語(yǔ)句, 執(zhí)行順序?yàn)?、2、5、6;

  • A2)拋出一個(gè)在catch 子句中捕獲的異常。

    • A2.1)如果catch子句沒(méi)有拋出異常, 程序?qū)?zhí)行try 語(yǔ)句塊之后的第一條語(yǔ)句, 在這里的執(zhí)行順序?yàn)?1、3、4、5、6;
    • A2.2)如果catch 子句拋出異常, 異常將被拋出這個(gè)方法的調(diào)用者, 在這里, 執(zhí)行順序?yàn)?1、3、5;
  • A3)代碼拋出了一個(gè)異常, 但catch 子句無(wú)法捕獲; 在這里, 執(zhí)行順序?yàn)?1、5;

1.4)try語(yǔ)句可以只有 finally子句,而沒(méi)有catch子句:如,

InputStream in = "..."; try {} finally {in.close(); }
  • 1.4.1)無(wú)論在try 語(yǔ)句塊中是否遇到異常,finally子句中的 in.close() 語(yǔ)句都會(huì)被執(zhí)行, 當(dāng)然, 如果真的遇到一個(gè)異常, 這個(gè)異常將會(huì)被重新拋出, 并且必須由另一個(gè)catch 子句捕獲;
  • 1.4.2)我們?cè)谛枰P(guān)閉資源的時(shí)候, 用這種方式使用 finally 子句是一個(gè)不錯(cuò) 的選擇;

Hint)這里, 強(qiáng)烈建議獨(dú)立使用 try/catch 和 try/finally 語(yǔ)句塊, 可以提高代碼的清晰度。如,(強(qiáng)烈推薦-strongly recommended)

InputStream in = "..."; try {try{code that might throw exceptions} finaly{in.close();} } catch(IOException e) {show error msg }
  • H1)內(nèi)層的try語(yǔ)句塊有一個(gè)職責(zé), 就是確保關(guān)閉輸入流;
  • H2)外層的try 語(yǔ)句塊也只有一個(gè)職責(zé), 就是確保報(bào)告出現(xiàn)的錯(cuò)誤;
  • H3)這種設(shè)計(jì)不僅清楚, 而且還將報(bào)告finally子句中出現(xiàn)的錯(cuò)誤;

Warning)

  • W1)當(dāng)finally子句包含 return 語(yǔ)句時(shí), 將會(huì)出現(xiàn)一種意想不到的結(jié)果;
  • W2)假設(shè)利用return 語(yǔ)句從try 語(yǔ)句塊中退出。 在這個(gè)方法返回前, finally子句的內(nèi)容將被執(zhí)行;

1.5)如果finally子句也有一個(gè) return, 這個(gè)返回值將會(huì)覆蓋原始的返回, 看個(gè)荔枝

public static int f(int n) {try{int r = n * n;return r;}finally{if(n==2) return 0;} }

對(duì)上述代碼的分析(Analysis):如果調(diào)用 f(2),那么try語(yǔ)句塊return 4, 而方法返回前, 還要執(zhí)行 finally子句, 其返回0, 這個(gè)返回值會(huì)覆蓋掉原始的返回值4**(即最終的返回值是0 而不是4);**

1.6)出現(xiàn)的問(wèn)題:

InputStream in = "..."; try {code that might throw exceptions } finally {in.close(); }
  • 1.6.1)問(wèn)題描述:對(duì)于上述代碼, 假設(shè)在 try 語(yǔ)句塊中的代碼拋出了 IOException異常, 這些異常只有這個(gè)方法的調(diào)用者才能夠處理。 執(zhí)行finally語(yǔ)句塊, 并調(diào)用close 方法。 而 close 方法本身也可能拋出 IOException異常。 當(dāng)出現(xiàn)這種case 時(shí), 原始的異常數(shù)據(jù)將丟失, 轉(zhuǎn)而拋出 close 方法的異常;
  • 1.6.2)解決方法: 如果你想做適當(dāng)處理的話, 重新拋出原來(lái)的異常,代碼會(huì)變得極其繁瑣;如下圖所示:
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語(yǔ)句

2.1)對(duì)于以下代碼模式:

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

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

try(Resource res) {work with res }
  • 2.2.1)try塊退出時(shí), 會(huì)自動(dòng)調(diào)用 res.close()。看個(gè)荔枝——讀取一個(gè)文件中的所有單詞:
try(Scanner in = new Scanner(new FileInputStream("/usr/.../"))) {while(in.hasNext())System.out.println(in.next()); }
  • 上述代碼中的 try塊正常退出時(shí), 或者存在一個(gè)異常時(shí), 都會(huì)調(diào)用 in.close()方法, 就好像使用了 finally塊一樣;
  • 2.2.2)還可以指定多個(gè) 資源:
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)無(wú)論這個(gè)塊如何退出, in 和 out 都會(huì)關(guān)閉: 如果你使用常規(guī)方式手動(dòng)編程,就需要兩個(gè)嵌套的 try/finally 子句;

Conclusion)

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

Attention)只要需要關(guān)閉資源, 就要盡可能地使用帶資源的 try語(yǔ)句;

總結(jié)

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

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。