暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

try-with-resource仅仅是一个语法糖吗?

有理想的菜鸡 2020-11-22
107

良心公众号

关注不迷路



01

管理外部资源的痛点


熟悉Java的小伙伴都知道,得益于JVM的垃圾回收机制,我们无需投入大量的精力在内存空间的管理上,但对于诸如文件、数据库连接、网络连接等外部资源的使用,就没那么幸运了。


由于外部资源无法由JVM进行管理,因此,必须在申请和使用相关的外部资源之后,必须进行显式的释放,否则,就会导致外部资源的泄漏,出现资源占用异常、连接池溢出等等一系列严重的问题。


为了避免上述问题的发生,在JDK1.7之前,我们只能通过一些列并不优雅的显式的外部资源释放逻辑,搭配以冗长的异常处理嵌套,来手动实现外部资源的释放。以文件资源为例,我们可以看一段JDK1.7之前文件资源使用的代码示例。


    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;


    public class FileTest {
    public static void main(String[] args) {
    FileOutputStream outputStream = null;
    try {
    System.out.println("start ^_^");
    outputStream = new FileOutputStream(new File("c:/test_files/test.txt"));
    outputStream.write("hello, test man!".getBytes());
    System.out.println("write file success ^o^");
    } catch (IOException e) {
    System.out.println("there is no such file!");
    } finally {
    if (outputStream != null) {
    try {
    outputStream.close();
    } catch (IOException e) {
    System.out.println("close file error!");
    }
    }
    }
    }
    }
    复制


    简单运行之后,将会得到如下结果:


      "JavaPath\Java\jdk-11.0.7\bin\java.exe" "-javaagent:IDEAPath\IntelliJ IDEA 2020.1.2\lib\idea_rt.jar=7242:IDEAPath\IntelliJ IDEA 2020.1.2\bin" -Dfile.encoding=UTF-8 -classpath C:\test\out\production\test FileTest
      start ^_^
      write file success ^o^


      Process finished with exit code 0
      复制



      虽然达到了向test.txt写入hello, test man!的目的,但代码看起来实在是不够优雅!


      02

      优雅地关闭外部资源


      为了解决这种尴尬的场面,JDK1.7增加了try-with-resource的语法,从JDK层面对外部的资源管理进行了支持,从而可以优雅地关闭外部资源。这听起来像一个语法糖,事实上,它确实是一个语法糖!但这个语法糖的内部实现,对我们日常的开发以及问题排查,是很有借鉴意义的。接下来,就让我们看看try-with-resource的具体实现吧。


      依旧以文件资源为例,我们采用try-with-resource的方式对上文中的程序加以改写。得到如下所示的程序:


        import java.io.File;
        import java.io.FileOutputStream;
        import java.io.IOException;


        public class FileTest {
        public static void main(String[] args) {
        try (FileOutputStream outputStream = new FileOutputStream(new File("c:/test_files/test.txt"));) {
        System.out.println("start ^_^");
        outputStream.write("hello, test man!".getBytes());
        System.out.println("write file success ^o^");
        } catch (IOException e) {
        System.out.println("there is no such file!");
        }
        }
        }


        复制


        相比之下,使用try-with-resource的方式,代码显得清爽多了,省去了编写finally代码块,代码的可读性更高了。那么try-with-resource到底是怎么做到维护外部资源的呢?


        上文提到了,它是JDK1.7新增的一个语法糖,既然是语法糖,那就并没有什么新的东西,只是JDK代你做了一些处理,从而优化了编码体验。具体细节我们可以看一下使用try-with-resource方式实现FileTest对应的class文件:


          //
          // Source code recreated from a .class file by IntelliJ IDEA
          // (powered by Fernflower decompiler)
          //


          import java.io.File;
          import java.io.FileOutputStream;
          import java.io.IOException;


          public class FileTest {
          public FileTest() {
          }


          public static void main(String[] args) {
          try {
          FileOutputStream outputStream = new FileOutputStream(new File("c:/test_files/test.txt"));


          try {
          System.out.println("start ^_^");
          outputStream.write("hello, test man!".getBytes());
          System.out.println("write file success ^o^");
          } catch (Throwable var5) {
          try {
          outputStream.close();
          } catch (Throwable var4) {
          var5.addSuppressed(var4);
          }


          throw var5;
          }


          outputStream.close();
          } catch (IOException var6) {
          System.out.println("there is no such file!");
          }


          }
          }
          复制


          03

          可靠的异常抑制


          看完之后是不是忍不住想起那句话:哪有什么岁月静好,不过是有人替你负重前行……感慨之余,这里面还有个细节,值得我们学习。在异常处理中的第26行代码内容为var5.addSuppressed(var4);这行代码使得抛出的外层异常,能够包含内层异常的相关信息。这就是所谓的异常抑制


          异常抑制对于排查问题,尤其是像本文的示例这样有异常嵌套的程序,具有十分重要的意义。因为它不会将内层异常的信息吞没,使得排查代码的线索丢失,反之,它将保留程序的完整异常栈,使排查问题显得有迹可循。这一点可以很好地利用到工作中复杂的异常处理场景中,从而提升代码的可维护性


          今天关于try-with-resource的总结就到这里了。


          欢迎大家一起讨论技术,共同成长!



          学习 | 工作 | 分享

          👆长按关注“有理想的菜鸡

          只有你想不到,没有你学不到
          文章转载自有理想的菜鸡,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

          评论