try-with-resource從入門到使用

try-with-resource是從java7開始提供的新特性。方便了我們資源的代碼編寫。下面展示一下代碼模板的對比
沒有try-with-resource

try{
    資源打開
    業(yè)務(wù)邏輯
}catch(Exception e){
    異常處理
}finally{
    資源關(guān)閉
}

try-with-resource的

try(資源打開){
    業(yè)務(wù)邏輯
}catch(Exception e){
    異常處理
}

案例分析

看了上面的模板,我們的一個直觀感覺是省去了finally,并且把資源放在了try后面的括號中。下面展示一段真實的代碼腔剂。

    public static void main(String[] args) {
        try (
                InputStream fileInputStream = Files.newInputStream(Paths.get("/Users/xie/delete/test.txt"));
                OutputStream outputStream = Files.newOutputStream(Paths.get("/Users/xie/delete/test2.txt"));
        ) {
            byte[] bytes = new byte[1024];
            int len;
            while ((len = fileInputStream.read(bytes)) > 0) {
                outputStream.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

注:上面的代碼只是演示了一個文件拷貝的方法,如果我們自己寫代碼請選擇1.7提供的Files.copy驼仪。

try-with-resource做了什么

我們通過反編譯工具來做一下對比

public static void main(String[] args) {
        try {
            InputStream fileInputStream = Files.newInputStream(Paths.get("/Users/xie/delete/test.txt"));
            Throwable var2 = null;
            try {
                OutputStream outputStream = Files.newOutputStream(Paths.get("/Users/xie/delete/test2.txt"));
                Throwable var4 = null;
                try {
                    byte[] bytes = new byte[1024];
                    int len;
                    while((len = fileInputStream.read(bytes)) > 0) {
                        outputStream.write(bytes, 0, len);
                    }
                } catch (Throwable var30) {
                    var4 = var30;
                    throw var30;
                } finally {
                    if (outputStream != null) {
                        if (var4 != null) {
                            try {
                                outputStream.close();
                            } catch (Throwable var29) {
                                var4.addSuppressed(var29);
                            }
                        } else {
                            outputStream.close();
                        }
                    }
                }
            } catch (Throwable var32) {
                var2 = var32;
                throw var32;
            } finally {
                if (fileInputStream != null) {
                    if (var2 != null) {
                        try {
                            fileInputStream.close();
                        } catch (Throwable var28) {
                            var2.addSuppressed(var28);
                        }
                    } else {
                        fileInputStream.close();
                    }
                }
            }
        } catch (IOException var34) {
            var34.printStackTrace();
        }
    }

基本從字節(jié)碼反編譯過來掸犬,我們可以看到他是按照我們熟悉的方式編寫的代碼袜漩。所以try-with-resource是語法糖。
這里大家不熟悉的可能就是一場處理里面有addSuppressed的調(diào)用湾碎。這是一個異常新加的方法噪服,抑制異常。其實這種場景很常見胜茧,一個方法里執(zhí)行出了多個異常,應(yīng)該報哪個呢仇味,雖然都能表示這個方法調(diào)用的失敗呻顽。以前的做法就是自己catch然后做一些邏輯操作,最后拋出一個丹墨。有了這個方法就能實現(xiàn)以前的邏輯廊遍,邏輯中也可以取出被抑制的異常信息。

使用的注意事項

  • 第三方庫的資源使用需要了解贩挣,他的資源是否實現(xiàn)了Closeable喉前。
    jdk的資源是都實現(xiàn)了這個接口。
class OutputStream implements Closeable, Flushable {

只有實現(xiàn)了Closeable的才可以和try-with-resource搭配使用王财。

  • 需要了解每個資源的關(guān)閉細(xì)節(jié)
    這里需要列舉兩個情況卵迂。
  1. socket的流的關(guān)閉會導(dǎo)致socket關(guān)閉。
    下面以inputstream為例绒净。SocketInputStream集成FileInputStream见咒,所以也實現(xiàn)了Closeable。
class SocketInputStream extends FileInputStream

但是他的close方法做的事情有點多挂疆,會檢測socket是否關(guān)閉改览。

    public void close() throws IOException {
        if (closing)
            return;
        closing = true;
        if (socket != null) {
            if (!socket.isClosed())
                socket.close();
        } else
            impl.close();
        closing = false;
    }
  1. 輸出流關(guān)閉沒有flush
    這是我調(diào)用別人寫的庫的時候遇到的問題,一直發(fā)現(xiàn)文件超過一定大小就會傳輸丟失缤言。習(xí)慣了很多庫都是close會順帶幫你做flush宝当。

上面的這些情況,本身就是使用流該注意的地方胆萧。

  • 資源聲明順序
    通過上面的例子庆揩,其實資源也是和我們自己寫代碼的思路一致,先聲明的后關(guān)閉跌穗。

9版本的改進(jìn)

java9之前的try-with-resource都是必須做一次賦值的盾鳞。

    public static void read(InputStream fileInputStream) {
        try (InputStream fileInputStreamTmp = fileInputStream) {
            byte[] bytes = new byte[1024];
            int len;
            while ((len = fileInputStreamTmp.read(bytes)) > 0) {
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

這個問題也挺明顯的,我都開始名字上加Tmp來標(biāo)識了瞻离。
9之后就徹底不用這么做了

    public static void read(InputStream fileInputStream) {
        try (fileInputStream) {
            byte[] bytes = new byte[1024];
            int len;
            while ((len = fileInputStream.read(bytes)) > 0) {

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腾仅,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子套利,更是在濱河造成了極大的恐慌推励,老刑警劉巖鹤耍,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異验辞,居然都是意外死亡稿黄,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門跌造,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杆怕,“玉大人,你說我怎么就攤上這事壳贪×暾洌” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵违施,是天一觀的道長互纯。 經(jīng)常有香客問我,道長磕蒲,這世上最難降的妖魔是什么留潦? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮辣往,結(jié)果婚禮上兔院,老公的妹妹穿的比我還像新娘。我一直安慰自己站削,他們只是感情好秆乳,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著钻哩,像睡著了一般屹堰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上街氢,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天扯键,我揣著相機與錄音,去河邊找鬼珊肃。 笑死荣刑,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的伦乔。 我是一名探鬼主播厉亏,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼烈和!你這毒婦竟也來了爱只?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤招刹,失蹤者是張志新(化名)和其女友劉穎恬试,沒想到半個月后窝趣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡训柴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年哑舒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幻馁。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡洗鸵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出仗嗦,到底是詐尸還是另有隱情膘滨,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布儒将,位于F島的核電站,受9級特大地震影響对蒲,放射性物質(zhì)發(fā)生泄漏钩蚊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一蹈矮、第九天 我趴在偏房一處隱蔽的房頂上張望砰逻。 院中可真熱鬧,春花似錦泛鸟、人聲如沸蝠咆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刚操。三九已至,卻和暖如春再芋,著一層夾襖步出監(jiān)牢的瞬間菊霜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工济赎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鉴逞,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓司训,卻偏偏與公主長得像构捡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子壳猜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容