1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

2021.05.02 更优雅地关闭流(Stream)

在日常开发中,我们会经常用到流(Stream),比如InputStream/OutPutStreamFileInputStream/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("结束");
}

不符合代码质量规范

上面这段代码,从逻辑上将是ok的,但是从代码质量的角度来说是不合格的,如果你用sonar或者sonarLint插件扫描你的项目的话,它会提示你存在Code smell,也就是合理的写法:

提示信息的意思是,你应该把第24行的代码改成try-with-resources的形式。这里简单补充一下,try-with-resoucesJDK1.7引入的,目的是优化资源关闭问题,将之前try-catch-finally优化成try-catch,之前你需要手动在finally中关闭,通过try-with-resouces的方式,你再也不用手动关闭你的各种流了。

try-with-resources方式

上面的代码优化后,是这样的:

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();
    }
}

区别

相比之前代码更简洁,唯一的区别是:

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

就是将你需要在try代码块中用到的资源,都放进try()中,这样你的资源就会自动被关闭。这种方式其实就是一种语法糖(对用户更更友好),从代码底层来说和前面手动关闭的方式区别不大,只是之前由你写关闭,现在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();
    } 
  }

发现新大陆

本来事情到这里应该结束了,但是我为了搞清楚本质区别,我在close()方法上打了断点,我想看下是不是我不关闭流,它就不自己关闭。

我先试了try-with-resouces地方式,close方法被调用,这是OK的;我又试了第一段的传统写法,close也被调用了。

但是我发现,close方法都被调用了两次,而且在第一段传统写法那里,是先调了close方法,然后再进入finally执行关闭。我已经有点困惑了,但我还是想再看下不手动关闭的情况,这次比前两次更神奇,close方法竟然也被调用了,太神奇了吧!

我还在想,JDK什么时候有这个新特性的,不竟然不知道,难道和我用JDK9有关,但查了资料,发现jdk9只是支持在try-with-resources中使用final修饰的变量,也没有这个呀,这时候我看了FileInputStream的源码,发现在FileInputStream的构造方法中,这样几行代码:

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

也就是在创建流的时候,会把当前流加入到FileDescriptor中,FileDescriptor有一个closeAll方法,会循环关闭加入其中的流,但是这个方法也只有在FileInputStreamclose中调用呀。

我还觉得是不是正常情况下会自动关闭,但是异常情况下不会关闭,但是试了异常情况下也会走到close方法,我裂了,难道是360替我关闭了?

这个问题我得再好好研究下,今天就到这里吧,温馨提示,假期余额不足

以下内容来源网络,侵删

posted @ 2021-05-03 10:48  云中志  阅读(298)  评论(0编辑  收藏  举报