增強(qiáng) try (Try-with-resources)

此心光明,亦復(fù)何言

Try-with-resources

Try-with-resources是Java7出現(xiàn)的一個(gè)新的異常處理機(jī)制,它能夠很容易地關(guān)閉在try-catch語(yǔ)句塊中使用的資源。

傳統(tǒng)的關(guān)閉資源方式是利用Try-Catch-Finally管理資源(舊的代碼風(fēng)格) 即在Java7以前程序中使用的資源需要被明確地關(guān)閉。

private static void printFile() throws IOException {
    InputStream input = null;
    try{
        input = new FileInputStream("d:\\hello.txt");
        int data = input.read();
        while(data != -1){
            System.out.print((char) data);
            data = input.read();
        }
    } finally {
        if(input != null){
            input.close();
        }   
    }       
}

以上程序 try語(yǔ)句塊中有3處能拋出異常,finally語(yǔ)句塊中有一處會(huì)拋出異常。

不論try語(yǔ)句塊中是否有異常拋出,finally語(yǔ)句塊始終會(huì)被執(zhí)行。這意味著,不論try語(yǔ)句塊中發(fā)生什么,InputStream 都會(huì)被關(guān)閉,或者說(shuō)都會(huì)試圖被關(guān)閉。如果關(guān)閉失敗,close()方法也可能會(huì)拋出異常。

假設(shè)try語(yǔ)句塊拋出一個(gè)異常,然后finally語(yǔ)句塊被執(zhí)行。同樣假設(shè)finally語(yǔ)句塊也拋出了一個(gè)異常。那么哪個(gè)異常會(huì)根據(jù)調(diào)用棧往外傳播?

即使try語(yǔ)句塊中拋出的異常與異常傳播更相關(guān),最終還是finally語(yǔ)句塊中拋出的異常會(huì)根據(jù)調(diào)用棧向外傳播。

在Java7以后,對(duì)于上面的例子可以用try-with-resource 結(jié)構(gòu)這樣寫(xiě):

private static void printFileJava7() throws IOException {
    try(FileInputStream input = new FileInputStream("d:\\hello.txt")) {
        int data = input.read();
        while(data != -1){
            System.out.print((char) data);
            data = input.read();
        }
    }   
}

注意方法中的第一行:

try(FileInputStream input = new FileInputStream("d:\\hello.txt"))

這就是try-with-resource 結(jié)構(gòu)的用法。FileInputStream 類(lèi)型變量就在try關(guān)鍵字后面的括號(hào)中聲明。而且一個(gè)FileInputStream 類(lèi)型被實(shí)例化并被賦給了這個(gè)變量。

當(dāng)try語(yǔ)句塊運(yùn)行結(jié)束時(shí),F(xiàn)ileInputStream 會(huì)被自動(dòng)關(guān)閉。這是因?yàn)镕ileInputStream 實(shí)現(xiàn)了java中的java.lang.AutoCloseable接口。所有實(shí)現(xiàn)了這個(gè)接口的類(lèi)都可以在try-with-resources結(jié)構(gòu)中使用。

當(dāng)try-with-resources結(jié)構(gòu)中拋出一個(gè)異常,同時(shí)FileInputStream被關(guān)閉時(shí)(調(diào)用了其close方法)也拋出一個(gè)異常,try-with-resources結(jié)構(gòu)中拋出的異常會(huì)向外傳播,而FileInputStream被關(guān)閉時(shí)拋出的異常被抑制了。這與文章開(kāi)始處利用舊風(fēng)格代碼的例子(在finally語(yǔ)句塊中關(guān)閉資源)相反。

使用多個(gè)資源

你也可以在塊中使用多個(gè)資源而且這些資源都能被自動(dòng)地關(guān)閉。下面是例子:

private static void printFileJava7() throws IOException {
    try(FileInputStream input = new FileInputStream("d:\\hello.txt"); BufferedInputStream bufferedInput = new BufferedInputStream(input))
    {
        int data = buffereInput.read();
        while(data != -1){
            System.out.println( (char) data);
            data = bufferedInput.read();
        }
    }
}

上面的例子在try關(guān)鍵字后的括號(hào)里創(chuàng)建了兩個(gè)資源——FileInputStream 和BufferedInputStream。當(dāng)程序運(yùn)行離開(kāi)try語(yǔ)句塊時(shí),這兩個(gè)資源都會(huì)被自動(dòng)關(guān)閉。

這些資源將按照他們被創(chuàng)建順序的逆序來(lái)關(guān)閉。首先BufferedInputStream 會(huì)被關(guān)閉,然后FileInputStream會(huì)被關(guān)閉。

自定義AutoCloseable 實(shí)現(xiàn)

這個(gè)try-with-resources結(jié)構(gòu)里不僅能夠操作java內(nèi)置的類(lèi)。你也可以在自己的類(lèi)中實(shí)現(xiàn)java.lang.AutoCloseable接口,然后在try-with-resources結(jié)構(gòu)里使用這個(gè)類(lèi)。

AutoClosable 接口僅僅有一個(gè)方法,接口定義如下:

public interface AutoClosable{
    public void close() throws Exception;
}

任何實(shí)現(xiàn)了這個(gè)接口的方法都可以在try-with-resources結(jié)構(gòu)中使用。下面是一個(gè)簡(jiǎn)單的例子:

public class MyAutoClosable implements AutoClosable{
    public void doIt(){
        System.out.println("MyAutoClosable doing it!");
    }

    @Override
    public void close() throws Exception{
        System.out.println("MyAutoCloseable Closed!");
    }
}

下面是MyAutoClosable 在try-with-resources結(jié)構(gòu)中使用的例子:

private static void myAutoClosable() throws Exception{
    try(MyAutoClosable myAutoClosable = new MyAutoClosable()){
        myAutoClosable.doIt();
    }
}

當(dāng)方法myAutoClosable.doIt()被調(diào)用時(shí),下面是打印到System.out的輸出:

MyAutoClosable doing it!
MyAutoClosable closed!

通過(guò)上面這些你可以看到,不論try-catch中使用的資源是自己創(chuàng)造的還是java內(nèi)置的類(lèi)型,try-with-resources都是一個(gè)能夠確保資源能被正確地關(guān)閉的強(qiáng)大方法。

小結(jié):

  • 自動(dòng)關(guān)閉資源的try語(yǔ)句相當(dāng)于包含了隱式的finally塊(用于關(guān)閉資源),因此這個(gè)try語(yǔ)句可以既沒(méi)有catch塊,也沒(méi)有finally塊。

  • 被自動(dòng)關(guān)閉的資源必須實(shí)現(xiàn)Closeable或AutoCloseable接口。(Closeable是AutoCloseable的子接口,Closeeable接口里的close()方法聲明拋出了IOException,;AutoCloseable接口里的close()方法聲明拋出了Exception)

    • Java7幾乎把所有的“資源類(lèi)”(包括文件IO的各種類(lèi),JDBC編程的Connection、Statement等接口……)進(jìn)行了改寫(xiě),改寫(xiě)后的資源類(lèi)都實(shí)現(xiàn)了AutoCloseable或Closeable接口
  • Java7新增的自動(dòng)關(guān)閉資源的try語(yǔ)句允許在try關(guān)鍵字后緊跟一對(duì)圓括號(hào),里面可以聲明、初始化一個(gè)或多個(gè)資源,此處的資源指的是那些必須在程序結(jié)束時(shí)顯示關(guān)閉的資源(數(shù)據(jù)庫(kù)連接、網(wǎng)絡(luò)連接等),try語(yǔ)句會(huì)在該語(yǔ)句結(jié)束時(shí)自動(dòng)關(guān)閉這些資源。

    • 被關(guān)閉的資源必須放在try語(yǔ)句后的圓括號(hào)中聲明、初始化。如果程序有需要自動(dòng)關(guān)閉資源的try語(yǔ)句后可以帶多個(gè)catch塊和一個(gè)finally塊。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ?try-with-resources語(yǔ)句是一個(gè)聲明一個(gè)或多個(gè)資源的 try 語(yǔ)句。一個(gè)資源作為一個(gè)對(duì)象,必須在程...
    xdoyf閱讀 3,539評(píng)論 0 0
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評(píng)論 19 139
  • 轉(zhuǎn)載自:http://mp.weixin.qq.com/s/LO1yyFeUA6pR_YPyfDoSig 姓名:梅...
    虐先森閱讀 1,488評(píng)論 0 1
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線(xiàn)程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,692評(píng)論 18 399
  • 原始文件README.MD: 修改文件 首先我們查看一下倉(cāng)庫(kù)狀態(tài): 我們做出這樣的修改: 僅僅在原始文件中加了個(gè)....
    Josaber閱讀 34,135評(píng)論 5 9

友情鏈接更多精彩內(nèi)容