Java中instanceof,談談Java的try..catch...

 2023-11-22 阅读 25 评论 0

摘要:2019獨角獸企業重金招聘Python工程師標準>>> 我們在寫Java的try..catch的時候,往往需要在最后加上finally子句關閉一些IO資源,比如 ? 1 2 3 4 5 6 7 8 9 10 11 12 InputStream?is; try { ???? is=openInputStream(); ???? //?do?something } catc

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

我們在寫Java的try..catch的時候,往往需要在最后加上finally子句關閉一些IO資源,比如

?

1
2
3
4
5
6
7
8
9
10
11
12
InputStream?is;
try {
???? is=openInputStream();
???? //?do?something
} catch (IOException?e){
???? e.printStaceTrace(e);
} finally {
???? try {
???????? is.close();
???? } catch (IOException?e?){
???? }
}
? ?

但 是在使用這種模式時,即使是Java老手,偶爾也會犯一些錯誤。比如上面這段代碼,當openInputStream()函數在執行過程中拋出異常,那么 變量is的值仍為null,此時執行is.close()會拋出NullPointerException. 由于NullPoiterException不是IOException的子類,因此它不能被catch塊捕獲,而是直接往調用層拋出去. 一種改進的寫法就是在關閉流的時候先進行非空判斷,但這樣代碼會顯得很啰嗦。個人認為比較優雅的寫法是直接調用commons-io包提供的 IOUtils.closeQuitely()方法關閉流(或者自己封裝一個closeQuitely()方法)。

使用這種寫法還有一種好處,就是當遇到關閉多個IO資源時不容易出錯,比如下面這段代碼:?

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
InputStream?is;
OutputStream?os?;
try {
???? is=openInputStream();
???? //?do?something
} catch (IOException?e){
???? e.printStaceTrace(e);
} finally {
???? try {
???????? if? (is?!=? null? )??is.close();
???????? if? (os?!=? null? )??os.close();
???? } catch (IOException?e?){
???? }
}
? ?

當is.close()發生錯誤的時候,os.close()就無法被執行,從而導致os所引用的資源沒有被釋放。?

也許Oracle也覺得這種try .. catch ... finally的樣板代碼太沒必要,因此在JDK 7中對try 子句進行了一些改造,免去編寫一些手動關閉資源的代碼,讓代碼看起來更緊湊更簡潔。比如上面的代碼在JDK 7下可以改成:

Java中instanceof。

1
2
3
4
5
6
7
8
try (
? InputStream?is?=?openInputStream();
? OutputStream?os?=?openOutStream();
){
?? //?do?something?
} catch (IOException?e){
???? e.printStaceTrace(e);
}
? ?

Oracle 把這里的try(..)語句叫做try-with-resource語句。需要注意的是,try(.. )中變量所引用的對象都必須是實現了java.io.AutoClosable接口的實例,當退出try ..catch塊時,JDK會自動調用close()方法。 也就是說,try-with-resource語句中的resource(資源)不僅限于IO資源。?

?

這里有必要對try-with-resource語句的一些細節進行補充說明:?

  • JDK會確保所有資源的close()方法被調用,不管close()方法是否拋出異常, 而調用的順序和資源聲明的順序相反

  • try-with-resource語句中所有拋出的異常都會被捕獲。如果多個異常被拋出,后面所拋出的異常會被suppress(抑 制)在前一個異常中,catch塊最終只拿到最先拋出的那個異常。可以依次通過調用Throwable類定義的getSuppressed()獲得被 suppressed(抑制)的異常

還是上面那個例子,

  • 當退出try .. catch.塊的時候,JDK會先調用os.close(),然后是is.close(), 如果兩次close()都拋出IOException, 那么is.close()所拋出的異常會被suppress(抑制)在os.close()所拋出的異常中,最終catch塊只捕獲到 os.close()所拋出的異常。可以通過getSuppressed()方法拿到is.close()所拋出的異常。

  • Java的final、如果調用openInputStream()的時候就發生IOException,那么openOutputStream()就不會被調 用,os.close()和is.close()也不會被調用, catch塊捕捉到 調用openInputStream()時所拋出的異常。?

  • 如果調用openOutputStream()發生IOException(用記號 e1表示), 那么is.close()還是會被調用, ?如果此時is.close()又拋出IOException(用記號 e2表示),那么e2會被suppress到e1中,而catch塊捕捉到的異常是 e1.?

?

除了對try塊做了改造,JDK 7還對catch部分進行了簡化,允許把多個catch子句合并。 比如:?

?

1
2
3
4
5
6
7
8
try (
? InputStream?is?=?openInputStream();
? OutputStream?os?=?openOutStream();
){
?? //?do?something???
} catch (IOException??| XMLParseException?|?XPathException e){
???? e.printStaceTrace(e);
}
? ?

?

此外,當你重新拋出多個異常時,不再需要詳細定義異常類型了,編譯器已經知道你具體拋出的是哪個異常了你只需在方法定義的時候聲明需要拋出的異常即可。比如

?

1
2
3
4
5
6
7
8
//?雖然這里用Exception匹配拋出的IOException,到編譯器知道實際上拋給上層的異常是IOException
???????? public? void? doIO()? throws? IOException?{
???????????? try {
???????????????? throw? new? IOException();
???????????? } catch (Exception?e){
???????????????? throw? e;
???????????? }
???????? }
? ?

PS : 這個特性我想不到會帶來什么好處

?

JDK 7還有其他有趣的語法新特性,比如二進制字面量,用下劃線分割長數字,泛型參數的類型推斷,switch支持字符串匹配等等。 現在JDK 8又引入了一些有用的特性。在不需要考慮向后兼容的前提下, 適當并靈活運用一些語法特性,可以讓我們的代碼在一定程度上顯得更清晰,更簡潔。

catch、

轉載于:https://my.oschina.net/u/131940/blog/621652

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/4/184567.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息