java异常—— finally 子句+带资源的 try语句
【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ì)變得極其繁瑣;如下圖所示:
【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è)方法:
Annotation)還有一個(gè) Closeable 接口, 它是 AutoCloseable 的子接口, 也包含一個(gè) close方法, 不過(guò), 這個(gè)方法聲明為拋出一個(gè) IOException;
2.2)帶資源的 try語(yǔ)句(try-with-resource)的最簡(jiǎn)單形式為:
- 2.2.1)try塊退出時(shí), 會(huì)自動(dòng)調(diào)用 res.close()。看個(gè)荔枝——讀取一個(gè)文件中的所有單詞:
- 上述代碼中的 try塊正常退出時(shí), 或者存在一個(gè)異常時(shí), 都會(huì)調(diào)用 in.close()方法, 就好像使用了 finally塊一樣;
- 2.2.2)還可以指定多個(gè) 資源:
- 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)題。
- 上一篇: 摩托罗拉手机a1200(摩托罗拉手机A1
- 下一篇: java异常——分析堆栈跟踪元素+使用异