<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)雅地關閉流(Stream)

          共 6863字,需瀏覽 14分鐘

           ·

          2021-05-09 20:25

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

          通常的關閉方式

          我們先看一段代碼:

           /**
               * 讀取文件
               */

          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 {
                  // 關閉資源
                  if (Objects.nonNull(fileInputStream)) {
                      try {
                          fileInputStream.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
              System.out.println("結束");
          }

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

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

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

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

          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)新大陸

          本來事情到這里應該結束了,但是我為了搞清楚本質區(qū)別,我在close()方法上打了斷點,我想看下是不是我不關閉流,它就不自己關閉。

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

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

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

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

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

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

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

          以下內容來源網絡,侵刪

          - END -


          瀏覽 45
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  亚洲国产视频中文字幕日不卡在线观看高清无码 | 十八岁禁黄网站 | 丁香狠狠色婷婷久久 | 国产激情无码视频 | 贵州18一20女人毛片毛片 |