Java类库中包括许多必须通过调用close方法来手工关闭的资源。例如InputStream、OutputStream和java.sql.Connection。客户端经常会忽略资源的关闭,造成严重的性能后果也就可想而知了。根据经验,try-finally 语句是确保资源会被适当关闭的最佳方法,就算是发生异常或者返回也一样:

public String tryfinally(String path) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(new File(path)));
    try{
        return reader.readLine();
    }finally {
        reader.close();
    }
}

即便用 try-finally 语句正确地关闭了资源,它也存在着些许不足。因为在try块和finally块中的代码,都会抛出异常。例如,底层的物理设备出现异常,那么调用readLine就会抛出异常,基于同样的原因,调用close也会出现异常。在这种情况下,第二个异常完全抹除了第一个异常。在异常堆栈轨迹中,完全没有关于第一个异常的记录,这在现实的系统中会导致调试变得非常复杂,因为通常需要看到第一个异常的记录,这在现实的系统中会导致调试变得非常复杂,因为通常需要看到第一个异常才能诊断出问题何在。虽然可以通过编写代码来禁止第二个异常,保留第一个异常,但事实上没有人会这么做,因为实现起来太繁琐了。

如何完美解决这种问题呢?当然是Java7中引入的 try-with-resources 语句。

还是上面的这段代码,使用 try-with-resources 语句之后,新的代码如下:

public String tryresources(String path) throws IOException {
    try(BufferedReader reader = new BufferedReader(new FileReader(new File(path)))){
        return reader.readLine();
    }
}

使用这种 try-with-resources 不仅使代码变得简洁易懂,也更容易进行诊断。以上段代码为例,如果调用 readLine 和 不可见的 close 方法都抛出异常,后一个异常就会被禁止,以保留第一个异常。事实上,为了保留你想看到的那个异常,即便多个异常都可以被禁止。这些被禁止的异常并不是简单地被抛弃了,而是会被打印在堆栈轨迹中,并注明它们是被禁止的异常。通过编程调用 getSuppressed 方法还可以访问到它们,getSuppressed 方法也已经添加在Java7的Throwable中了。

使用 try-with-resources 语句有什么要求吗?

是的,要使用这个构造的资源,必须先实现 AutoCloseable 接口,其中包含了单个返回 void 的 close 方法。Java类库与第三方类库中的许多类和接口,现在都实现或扩展了 AutoCloseable 接口。

public interface AutoCloseable {
    void close() throws Exception;
}

以下是使用 try-with-resources 的第二个范例:

void tryresources(String src,String dst) throws IOException {
     try(InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(dst)){
        byte[] bytes = new byte[1024];
        int n;
        while ((n=in.read(bytes))>=0){
            out.write(bytes,0,n);
        }
     }
}

在 try-with-resources 语句中还可以使用 catch 子句,就像在平时的 try-finally 语句中一样。

public String tryresources(String path){
   try(BufferedReader reader = new BufferedReader(new FileReader(new File(path)))){
        return reader.readLine();
   } catch (IOException e) {
         return null;
   }
}

有了 try-with-resources 语句,在使用必须关闭的资源时,就能更轻松地正确编写代码了。

使用try-with-resources优雅的关闭IO流的更多相关文章

  1. Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)

    声明:该博文以socket中,关闭输出流为例进行说明. 为了方便讲解,我们把DataOutputstream dout = new DataOutputStream(new BufferedOutpu ...

  2. Android—Socket中关闭IO流后导致Socket关闭不能再收发数据的解决办法

    以Socket发送数据为例: 发送数据时候要声明:DataOutputStream os = new DataOutputStream(socket.getOutputStream()); 最近开发遇 ...

  3. 分页写入文件,第二次分页前一定要关闭IO流啊。。否则文件写不全。。- -粗心

  4. JavaSE | IO流

    java.io.File类(文件和目录路径名的抽象表示形式) 如果希望在程序中操作文件和目录都可以通过File类来完成,File类能新建.删除.重命名文件和目录. File类是文件或目录的路径,而不是 ...

  5. JAVA之IO流(字节流)

    输入和输出 JAVA的流分为输入流和输出流两部分, 输入流:InputStream或者Reader:从文件中读到程序中: 输出流:OutputStream或者Writer:从程序中输出到文件中: Re ...

  6. Java IO流

    File类 ·java.io.File类:文件和目录路径名的抽象表示形式,与平台无关 ·File能新建.删除.重命名文件和目录,但File不能访问文件内容本身.如果需要访问文件内容本身,则需要使用输入 ...

  7. RandomAccessFile&IO流&排序&方法论

    RandomAccessFile&IO流&排序&方法论 我们总觉得历史是极其遥远的东西,与我们并无关联,又觉得历史隐藏在图书馆的旧书之中. 然而,我们每个人都有真真切切的历史. ...

  8. IO流简要总结

    IO流小总结 IO流的本质就是用于数据的传输,根据流的方向的不同,有输入流.输出流.根据数据类型的不同,又有字节流.字符流. 字节流 字节输入流   InputStream 字节输出流   Outpu ...

  9. 第十一章 IO流

    11.IO流 11.1 java.io.File类的使用 1课时 11.2 IO原理及流的分类 1课时 11.3 节点流(或文件流) 1课时 11.4 缓冲流 1课时 11.5 转换流 1课时 11. ...

随机推荐

  1. 【RL-TCPnet网络教程】第40章 RL-TCPnet之TFTP客户端(精简版)

    第40章      RL-TCPnet之TFTP客户端 本章节为大家讲解RL-TCPnet的TFTP客户端应用,学习本章节前,务必要优先学习第38章的TFTP基础知识.有了这些基础知识之后,再搞本章节 ...

  2. 百度APP移动端网络深度优化实践分享(一):DNS优化篇

    本文由百度技术团队“蔡锐”原创发表于“百度App技术”公众号,原题为<百度App网络深度优化系列<一>DNS优化>,感谢原作者的无私分享. 一.前言 网络优化是客户端几大技术方 ...

  3. Java核心技术第五章——1.类、超类、子类(2)

    继上一篇Java核心技术第五章——1.类.超类.子类(1) 6.重载解析 假如调用ClassName.Method(args) 1.编译器列出类ClassName所有名为Method的方法. 2.编译 ...

  4. springboot项目上传文件出现临时文件目录为空

    最近写文件上传到服务器读取的代码,前端使用FormData上传,服务端用MultipartFile接收,自己测试了下MultipartFile对象有什么东西,结果一般属性都能出来,测试getInput ...

  5. SpringMVC 参数传递和接收的几种方式

    普通传参 测试项目:SpringBoot2.0.不使用 form 表单传参,后端不需要指定 consumes . 使用 Postman 进行测试. @PathVariable 只能接收 URL 路径里 ...

  6. python的进程与线程(三)

    线程的锁 1.几个概念 讲起线程的锁,先要了解几个概念:什么是并行?什么是并发?什么是同步?什么是异步?          并发:是指系统具有处理多个任务(动作)的能力          并行:是指系 ...

  7. IDEA代码格式化快捷键(新)

    快捷键:Ctrl+Alt+L 效果: 之前: 之后:

  8. AsyncTask原理

    一.概述 Android开发中我们通常让主线程负责前台用户界面的绘制以及响应用户的操作,让工作者线程在后台执行一些比较耗时的任务.Android中的工作者线程主要有AsyncTask.IntentSe ...

  9. Wolsey "强整数规划“ 建模的+Leapms实践——无产能批量问题

    Wolsey "强整数规划“ 建模的+Leapms实践——无产能批量问题 <整数规划>[1]一书作者L. A. Wolsey对批量问题(Lot-sizing Problem)做了 ...

  10. Docker进阶之四:centos7安装docker

    centos7.6 安装docker 参考:https://docs.docker.com/install/linux/docker-ce/centos/ 一.存在老版本先删除 yum remove ...