栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

try-with-resource从入门到使用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

try-with-resource从入门到使用

try-with-resource是从java7开始提供的新特性。方便了我们资源的代码编写。下面展示一下代码模板的对比
没有try-with-resource

try{
	资源打开
	业务逻辑
}catch(Exception e){
	异常处理
}finally{
	资源关闭
}

try-with-resource的

try(资源打开){
	业务逻辑
}catch(Exception e){
	异常处理
}

案例分析

看了上面的模板,我们的一个直观感觉是省去了finally,并且把资源放在了try后面的括号中。下面展示一段真实的代码。

    public static void main(String[] args) {
 try (
  InputStream fileInputStream = Files.newInputStream(Paths.get("/Users/xie/delete/test.txt"));
  OutputStream outputStream = Files.newOutputStream(Paths.get("/Users/xie/delete/test2.txt"));
 ) {
     byte[] bytes = new byte[1024];
     int len;
     while ((len = fileInputStream.read(bytes)) > 0) {
  outputStream.write(bytes, 0, len);
     }
 } catch (IOException e) {
     e.printStackTrace();
 }
    }

注:上面的代码只是演示了一个文件拷贝的方法,如果我们自己写代码请选择1.7提供的Files.copy。

try-with-resource做了什么

我们通过反编译工具来做一下对比

public static void main(String[] args) {
 try {
     InputStream fileInputStream = Files.newInputStream(Paths.get("/Users/xie/delete/test.txt"));
     Throwable var2 = null;
     try {
  OutputStream outputStream = Files.newOutputStream(Paths.get("/Users/xie/delete/test2.txt"));
  Throwable var4 = null;
  try {
      byte[] bytes = new byte[1024];
      int len;
      while((len = fileInputStream.read(bytes)) > 0) {
   outputStream.write(bytes, 0, len);
      }
  } catch (Throwable var30) {
      var4 = var30;
      throw var30;
  } finally {
      if (outputStream != null) {
   if (var4 != null) {
try {
    outputStream.close();
} catch (Throwable var29) {
    var4.addSuppressed(var29);
}
   } else {
outputStream.close();
   }
      }
  }
     } catch (Throwable var32) {
  var2 = var32;
  throw var32;
     } finally {
  if (fileInputStream != null) {
      if (var2 != null) {
   try {
fileInputStream.close();
   } catch (Throwable var28) {
var2.addSuppressed(var28);
   }
      } else {
   fileInputStream.close();
      }
  }
     }
 } catch (IOException var34) {
     var34.printStackTrace();
 }
    }

基本从字节码反编译过来,我们可以看到他是按照我们熟悉的方式编写的代码。所以try-with-resource是语法糖。
这里大家不熟悉的可能就是一场处理里面有addSuppressed的调用。这是一个异常新加的方法,抑制异常。其实这种场景很常见,一个方法里执行出了多个异常,应该报哪个呢,虽然都能表示这个方法调用的失败。以前的做法就是自己catch然后做一些逻辑操作,最后抛出一个。有了这个方法就能实现以前的逻辑,逻辑中也可以取出被抑制的异常信息。

使用的注意事项
  • 第三方库的资源使用需要了解,他的资源是否实现了Closeable。
    jdk的资源是都实现了这个接口。
class OutputStream implements Closeable, Flushable {

只有实现了Closeable的才可以和try-with-resource搭配使用。

  • 需要了解每个资源的关闭细节
    这里需要列举两个情况。
  1. socket的流的关闭会导致socket关闭。
    下面以inputstream为例。SocketInputStream集成FileInputStream,所以也实现了Closeable。
class SocketInputStream extends FileInputStream

但是他的close方法做的事情有点多,会检测socket是否关闭。

    public void close() throws IOException {
 if (closing)
     return;
 closing = true;
 if (socket != null) {
     if (!socket.isClosed())
  socket.close();
 } else
     impl.close();
 closing = false;
    }
  1. 输出流关闭没有flush
    这是我调用别人写的库的时候遇到的问题,一直发现文件超过一定大小就会传输丢失。习惯了很多库都是close会顺带帮你做flush。

上面的这些情况,本身就是使用流该注意的地方。

  • 资源声明顺序
    通过上面的例子,其实资源也是和我们自己写代码的思路一致,先声明的后关闭。
9版本的改进

java9之前的try-with-resource都是必须做一次赋值的。

    public static void read(InputStream fileInputStream) {
 try (InputStream fileInputStreamTmp = fileInputStream) {
     byte[] bytes = new byte[1024];
     int len;
     while ((len = fileInputStreamTmp.read(bytes)) > 0) {
     }
 } catch (IOException e) {
     e.printStackTrace();
 }
    }

这个问题也挺明显的,我都开始名字上加Tmp来标识了。
9之后就彻底不用这么做了

    public static void read(InputStream fileInputStream) {
 try (fileInputStream) {
     byte[] bytes = new byte[1024];
     int len;
     while ((len = fileInputStream.read(bytes)) > 0) {

     }
 } catch (IOException e) {
     e.printStackTrace();
 }
    }
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号