<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何更優(yōu)雅地關(guān)閉流(Stream)?

          共 3648字,需瀏覽 8分鐘

           ·

          2021-11-30 07:35

          在日常開發(fā)中,我們會經(jīng)常用到流(Stream),比如InputStream/OutPutStreamFileInputStream/FileOutPutStream等,你是不是經(jīng)常像下面展示的這樣手動關(guān)閉流,或者甚至都不關(guān)閉流呢?今天我們就來探討下關(guān)于流關(guān)閉的問題。

          通常的關(guān)閉方式

          我們先看一段代碼:

          ?/**
          ?????*?讀取文件
          ?????*/

          private?static?void?readFile()?{
          ????FileInputStream?fileInputStream?=?null;
          ????try?{
          ????????fileInputStream?=?new?FileInputStream("target/classes/test.txt");
          ????????byte[]?bytes?=?new?byte[1024];
          ????????//?讀取文件
          ????????while?(fileInputStream.read(bytes)?!=?-1)?{
          ????????????System.out.println(new?String(bytes));
          ????????}
          ????????System.out.println(1/0);
          ????????System.out.println(fileInputStream.available());
          ????}?catch?(FileNotFoundException?e)?{
          ????????e.printStackTrace();
          ????}?catch?(IOException?e)?{
          ????????e.printStackTrace();
          ????}?finally?{
          ????????//?關(guān)閉資源
          ????????if?(Objects.nonNull(fileInputStream))?{
          ????????????try?{
          ????????????????fileInputStream.close();
          ????????????}?catch?(IOException?e)?{
          ????????????????e.printStackTrace();
          ????????????}
          ????????}
          ????}
          ????System.out.println("結(jié)束");
          }

          不符合代碼質(zhì)量規(guī)范

          上面這段代碼,從邏輯上將是ok的,但是從代碼質(zhì)量的角度來說是不合格的,如果你用sonar或者sonarLint插件掃描你的項(xiàng)目的話,它會提示你存在Code smell,也就是合理的寫法:

          提示信息的意思是,你應(yīng)該把第24行的代碼改成try-with-resources的形式。這里簡單補(bǔ)充一下,try-with-resoucesJDK1.7引入的,目的是優(yōu)化資源關(guān)閉問題,將之前try-catch-finally優(yōu)化成try-catch,之前你需要手動在finally中關(guān)閉,通過try-with-resouces的方式,你再也不用手動關(guān)閉你的各種流了。

          try-with-resources方式

          上面的代碼優(yōu)化后,是這樣的:

          private?static?void?readFile2()?{
          ????try?(FileInputStream?fileInputStream?=?new?FileInputStream("target/classes/test.txt"))?{
          ????????byte[]?bytes?=?new?byte[1024];
          ????????//?讀取文件
          ????????while?(fileInputStream.read(bytes)?!=?-1)?{
          ????????????System.out.println(new?String(bytes));
          ????????}
          ?????????throw?new?FileNotFoundException("");
          ????}?catch?(FileNotFoundException?e)?{
          ????????e.printStackTrace();
          ????}?catch?(IOException?e)?{
          ????????e.printStackTrace();
          ????}
          }

          區(qū)別

          相比之前代碼更簡潔,唯一的區(qū)別是:

          try?(FileInputStream?fileInputStream?=?new?FileInputStream("target/classes/test.txt"))?{

          就是將你需要在try代碼塊中用到的資源,都放進(jìn)try()中,這樣你的資源就會自動被關(guān)閉。這種方式其實(shí)就是一種語法糖(對用戶更更友好),從代碼底層來說和前面手動關(guān)閉的方式區(qū)別不大,只是之前由你寫關(guān)閉,現(xiàn)在jdk在編譯的時(shí)候,會自己加,下面反編譯的代碼,很好地說明了這一點(diǎn):

          private?static?void?readFile2()?{
          ????try?{
          ??????FileInputStream?fileInputStream?=?new?FileInputStream("target/classes/test.txt");
          ??????Throwable?throwable?=?null;
          ??????try?{
          ????????byte[]?bytes?=?new?byte[1024];
          ????????while?(fileInputStream.read(bytes)?!=?-1)
          ??????????System.out.println(new?String(bytes));?
          ????????throw?new?FileNotFoundException("");
          ??????}?catch?(Throwable?throwable1)?{
          ????????throwable?=?throwable1?=?null;
          ????????throw?throwable1;
          ??????}?finally?{
          ????????if?(throwable?!=?null)?{
          ??????????try?{
          ????????????fileInputStream.close();
          ??????????}?catch?(Throwable?throwable1)?{
          ????????????throwable.addSuppressed(throwable1);
          ??????????}?
          ????????}?else?{
          ??????????fileInputStream.close();
          ????????}?
          ??????}?
          ????}?catch?(FileNotFoundException?e)?{
          ??????e.printStackTrace();
          ????}?catch?(IOException?e)?{
          ??????e.printStackTrace();
          ????}?
          ??}

          發(fā)現(xiàn)新大陸

          本來事情到這里應(yīng)該結(jié)束了,但是我為了搞清楚本質(zhì)區(qū)別,我在close()方法上打了斷點(diǎn),我想看下是不是我不關(guān)閉流,它就不自己關(guān)閉。

          我先試了try-with-resouces的方式,close方法被調(diào)用,這是OK的;我又試了第一段的傳統(tǒng)寫法,close也被調(diào)用了。

          但是我發(fā)現(xiàn),close方法都被調(diào)用了兩次,而且在第一段傳統(tǒng)寫法那里,是先調(diào)了close方法,然后再進(jìn)入finally執(zhí)行關(guān)閉。我已經(jīng)有點(diǎn)困惑了,但我還是想再看下不手動關(guān)閉的情況,這次比前兩次更神奇,close方法竟然也被調(diào)用了,太神奇了吧!

          我還在想,JDK什么時(shí)候有這個(gè)新特性的,不竟然不知道,難道和我用JDK9有關(guān),但查了資料,發(fā)現(xiàn)jdk9只是支持在try-with-resources中使用final修飾的變量,也沒有這個(gè)呀,這時(shí)候我看了FileInputStream的源碼,發(fā)現(xiàn)在FileInputStream的構(gòu)造方法中,這樣幾行代碼:

          ?fd?=?new?FileDescriptor();
          ?fd.attach(this);

          也就是在創(chuàng)建流的時(shí)候,會把當(dāng)前流加入到FileDescriptor中,FileDescriptor有一個(gè)closeAll方法,會循環(huán)關(guān)閉加入其中的流,但是這個(gè)方法也只有在FileInputStreamclose中調(diào)用呀。

          我還覺得是不是正常情況下會自動關(guān)閉,但是異常情況下不會關(guān)閉,但是試了異常情況下也會走到close方法,我裂了,難道是360替我關(guān)閉了

          這個(gè)問題我得再好好研究下,今天就到這里吧,溫馨提示,假期余額不足

          以下內(nèi)容來源網(wǎng)絡(luò),侵刪

          - END -


          瀏覽 110
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  淫荡留学生激情 | 天天看av | 日韩 欧美 亚洲 | 手机黄色在线 | 天天干天天射天天快乐 |