gpt4 book ai didi

使用try-with-resource的输入输出流自动关闭

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 24 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章使用try-with-resource的输入输出流自动关闭由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

try-with-resource的输入输出流自动关闭

最近在做代码审核的时候,审核工具提示我将 try-catch-finally 给替换掉,而且根据公司相关要求,该提示的级别还不低,不改不予通过.

先看看代码吧:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
FileReader fr = null
BufferedReader br = null ;
try {
     fr = new FileReader(fileName);
     br = new BufferedReader(fr);
     return br.readLine();
} catch (Exception e) {
     log.error( "error:{}" , e);
} finally {
   if (br != null ) {
     try {
       br.close();
     } catch (IOException e){
       log.error( "error:{}" , e);
     }
   }
   if (fr != null ) {
     try {
       br.close();
     } catch (IOException e){
       log.error( "error:{}" , e);
     }
   }
}

审核工具给出的意见是 替换为:

?
1
2
3
4
5
6
7
8
try (
     FileReader fr = new FileReader(fileName);
     BufferedReader br = new BufferedReader(fr)
   ) {
     return br.readLine();
} catch (Exception e) {
     log.error( "error:{}" , e);
}

或者是:

?
1
2
3
4
5
6
7
8
9
try (
     BufferedReader br = new BufferedReader( new FileReader(fileName))
   ) {
     // no need to name intermediate resources if you don't want to
     return br.readLine();
}
catch (Exception e) {
     log.error( "error:{}" , e);
}

对比代码,不难发现,输入输出流的关闭存在着差异。难道输入输出流不用关闭了吗?

带着这个问题看看源代码,发现

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class FileInputStream extends InputStream{}
public abstract class InputStream implements Closeable {}
/**
  * A {@code Closeable} is a source or destination of data that can be closed.
  * The close method is invoked to release resources that the object is
  * holding (such as open files).
  *
  * @since 1.5
  */
public interface Closeable extends AutoCloseable {}
/**
  * An object that may hold resources (such as file or socket handles)
  * until it is closed. The {@link #close()} method of an {@code AutoCloseable}
  * object is called automatically when exiting a {@code
  * try}-with-resources block for which the object has been declared in
  * the resource specification header. This construction ensures prompt
  * release, avoiding resource exhaustion exceptions and errors that
  * may otherwise occur.
  *
  * @apiNote
  * <p>It is possible, and in fact common, for a base class to
  * implement AutoCloseable even though not all of its subclasses or
  * instances will hold releasable resources.  For code that must operate
  * in complete generality, or when it is known that the {@code AutoCloseable}
  * instance requires resource release, it is recommended to use {@code
  * try}-with-resources constructions. However, when using facilities such as
  * {@link java.util.stream.Stream} that support both I/O-based and
  * non-I/O-based forms, {@code try}-with-resources blocks are in
  * general unnecessary when using non-I/O-based forms.
  *
  * @author Josh Bloch
  * @since 1.7
  */
public interface AutoCloseable {}

AutoCloseable 顾名思义, 自动关闭流. 从注释中我们可以发现,实现了AutoCloseable并在try()中声明的对象,当try-with-resource代码块执行完的时候,会自动调用close()方法.

注意:

一个 try-with-resources 语句可以像普通的 try 语句那样有 catch 和 finally 块。在try-with-resources 语句中, 任意的 catch 或者 finally 块都是在声明的资源被关闭以后才运行.

使用try-with-resource需要注意的地方

try-with-resource是JDK7引入的语法糖,可以简化Autocloseable资源类的关闭过程, 。

比如JDK7以前下面的代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
File file = new File( "d:/tmp/1.txt" );
  FileInputStream fis = null ;
  try {
   fis = new FileInputStream(file);
   xxxxx
            xxxxx
  } catch (IOException e) {
   e.printStackTrace();
  } finally {
   if (fis != null ){
    try {
     fis.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }

上面是一段读取文件内容的示意代码,为了防止在try代码块中出现异常后导致的资源泄露问题,在finally代码块中一般处理资源的关闭事项.

JDK之后上面的代码就可以简化成下面的写法:

?
1
2
3
4
5
6
7
File file = new File( "d:/tmp/1.txt" );
try (FileInputStream fis = new FileInputStream(file);) {
  fis.read();
} catch (IOException e) {
  e.printStackTrace();
} finally {
}

可以看出是简化了不少,之所以称之为语法糖,是因为编译成class文件后实际的代码就不是这样的了,编译过程中会自动添加资源的关闭处理.

上面的代码编译出的class文件使用javap进行反编译后是下面这样的

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
File file = new File( "d:/tmp/1.txt" );
   try {
    Throwable var2 = null ;
    Object var3 = null ;
 
    try {
     FileInputStream fis = new FileInputStream(file);
                 xxx
                 xxxx
    } catch (Throwable var12) {
     if (var2 == null ) {
      var2 = var12;
     } else if (var2 != var12) {
      var2.addSuppressed(var12);
     }
     throw var2;
    }
   } catch (IOException var13) {
    var13.printStackTrace();
   }

好了,上面已经引入今天的主题,try-with-resource,但是仍然有需要注意的地方.

比如下面的代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private static class MyResource implements AutoCloseable{
   private MyResource1 res; 
   public MyResource(MyResource1 res){
    this .res = res;
   }
  
   @Override
   public void close() throws Exception {
    System.out.println( "MyResource自动关闭" );
    Integer a = null ;
    a.toString();
    this .res.close();
   }
  }
 
  private static class MyResource1 implements AutoCloseable{
   @Override
   public void close() throws Exception {
    System.out.println( "MyResource1自动关闭" );
   }
  }
 
  @Test
  public void test() throws Exception{
   try (
     MyResource r = new MyResource( new MyResource1())){
    Integer a = null ;
    a.toString();
   }
  }

执行上面的代码,由于MyResource的close方法中出现了异常,此时创建的MyResource1就不会被关闭,从而出现资源泄露情况,为了规避这个问题,为了规避这个问题,我们需要创建的实现AutoCloseable接口的对象单独创建.

如下面所示:

?
1
2
3
4
5
6
try (
   MyResource1 res= new MyResource1();
   MyResource r = new MyResource(res)){
  Integer a = null ;
  a.toString();
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我.

原文链接:https://blog.csdn.net/wangjie_19920912/article/details/69501883 。

最后此篇关于使用try-with-resource的输入输出流自动关闭的文章就讲到这里了,如果你想了解更多关于使用try-with-resource的输入输出流自动关闭的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com