一、背景
成都創(chuàng)新互聯(lián)專注于網(wǎng)站建設(shè)|企業(yè)網(wǎng)站維護(hù)|優(yōu)化|托管以及網(wǎng)絡(luò)推廣,積累了大量的網(wǎng)站設(shè)計(jì)與制作經(jīng)驗(yàn),為許多企業(yè)提供了網(wǎng)站定制設(shè)計(jì)服務(wù),案例作品覆蓋發(fā)電機(jī)回收等行業(yè)。能根據(jù)企業(yè)所處的行業(yè)與銷售的產(chǎn)品,結(jié)合品牌形象的塑造,量身開發(fā)品質(zhì)網(wǎng)站。
我們知道,在Java編程過程中,如果打開了外部資源(文件、數(shù)據(jù)庫連接、網(wǎng)絡(luò)連接等),我們必須在這些外部資源使用完畢后,手動(dòng)關(guān)閉它們。因?yàn)橥獠抠Y源不由JVM管理,無法享用JVM的垃圾回收機(jī)制,如果我們不在編程時(shí)確保在正確的時(shí)機(jī)關(guān)閉外部資源,就會(huì)導(dǎo)致外部資源泄露,緊接著就會(huì)出現(xiàn)文件被異常占用,數(shù)據(jù)庫連接過多導(dǎo)致連接池溢出等諸多很嚴(yán)重的問題。
二、傳統(tǒng)的資源關(guān)閉方式
為了確保外部資源一定要被關(guān)閉,通常關(guān)閉代碼被寫入finally代碼塊中,當(dāng)然我們還必須注意到關(guān)閉資源時(shí)可能拋出的異常,于是變有了下面的經(jīng)典代碼:
public static void main(String[] args) { FileInputStream inputStream = null; try { inputStream = new FileInputStream(new File("test")); System.out.println(inputStream.read()); } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } } } }
熟悉其他語言的朋友可能會(huì)開始吐槽了,在C++中,我們可以把關(guān)閉資源的代碼放在析構(gòu)函數(shù)中,在C#中,我們有using代碼塊。這些語法都有一個(gè)共同的特性,讓外部資源的關(guān)閉行為與外部資源的句柄對(duì)象的生命周期關(guān)聯(lián),當(dāng)外部資源的句柄對(duì)象生命周期終結(jié)時(shí)(例如句柄對(duì)象已出作用域),外部資源的關(guān)閉行為將被自動(dòng)調(diào)用。這樣不僅更加符合面向?qū)ο蟮木幊汤砟睿▽㈥P(guān)閉外部資源的行為內(nèi)聚在外部資源的句柄對(duì)象中),也讓代碼更加簡(jiǎn)潔易懂。怎么到了Java這里,就找不到自動(dòng)關(guān)閉外部資源的語法特性了呢。
三、JDK7及其之后的資源關(guān)閉方式
3.1 try-with-resource語法
確實(shí),在JDK7以前,Java沒有自動(dòng)關(guān)閉外部資源的語法特性,直到JDK7中新增了try-with-resource語法,才實(shí)現(xiàn)了這一功能。
那什么是try-with-resource呢?簡(jiǎn)而言之,當(dāng)一個(gè)外部資源的句柄對(duì)象(比如FileInputStream對(duì)象)實(shí)現(xiàn)了AutoCloseable接口,那么就可以將上面的板式代碼簡(jiǎn)化為如下形式:
public static void main(String[] args) { try (FileInputStream inputStream = new FileInputStream(new File("test"))) { System.out.println(inputStream.read()); } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } }
將外部資源的句柄對(duì)象的創(chuàng)建放在try關(guān)鍵字后面的括號(hào)中,當(dāng)這個(gè)try-catch代碼塊執(zhí)行完畢后,Java會(huì)確保外部資源的close方法被調(diào)用。代碼是不是瞬間簡(jiǎn)潔許多!
3.2 實(shí)現(xiàn)原理
try-with-resource并不是JVM虛擬機(jī)的新增功能,只是JDK實(shí)現(xiàn)了一個(gè)語法糖,當(dāng)你將上面代碼反編譯后會(huì)發(fā)現(xiàn),其實(shí)對(duì)JVM虛擬機(jī)而言,它看到的依然是之前的寫法:
public static void main(String[] args) { try { FileInputStream inputStream = new FileInputStream(new File("test")); Throwable var2 = null; try { System.out.println(inputStream.read()); } catch (Throwable var12) { var2 = var12; throw var12; } finally { if (inputStream != null) { if (var2 != null) { try { inputStream.close(); } catch (Throwable var11) { var2.addSuppressed(var11); } } else { inputStream.close(); } } } } catch (IOException var14) { throw new RuntimeException(var14.getMessage(), var14); } }
3.3 異常抑制
通過反編譯的代碼,大家可能注意到代碼中有一處對(duì)異常的特殊處理:
var2.addSuppressed(var11);
這是try-with-resource語法涉及的另外一個(gè)知識(shí)點(diǎn),叫做異常抑制。當(dāng)對(duì)外部資源進(jìn)行處理(例如讀或?qū)懀r(shí),如果遭遇了異常,且在隨后的關(guān)閉外部資源過程中,又遭遇了異常,那么你catch到的將會(huì)是對(duì)外部資源進(jìn)行處理時(shí)遭遇的異常,關(guān)閉資源時(shí)遭遇的異常將被“抑制”但不是丟棄,通過異常的getSuppressed方法,可以提取出被抑制的異常。
四、總結(jié)
1、當(dāng)一個(gè)外部資源的句柄對(duì)象實(shí)現(xiàn)了AutoCloseable接口,JDK7中便可以利用try-with-resource語法更優(yōu)雅的關(guān)閉資源,消除板式代碼。
2、try-with-resource時(shí),如果對(duì)外部資源的處理和對(duì)外部資源的關(guān)閉均遭遇了異常,“關(guān)閉異?!睂⒈灰种?,“處理異?!睂⒈粧伋?,但“關(guān)閉異?!辈]有丟失,而是存放在“處理異?!钡谋灰种频漠惓A斜碇?。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
網(wǎng)站題目:Java如何優(yōu)雅地關(guān)閉資源try-with-resource及其異常抑制
網(wǎng)頁鏈接:http://www.rwnh.cn/article34/jdcgpe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、用戶體驗(yàn)、網(wǎng)站維護(hù)、域名注冊(cè)、電子商務(wù)、微信公眾號(hào)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)