如果我们使用 try-with-resource 是不是需要关闭资源

Posted

技术标签:

【中文标题】如果我们使用 try-with-resource 是不是需要关闭资源【英文标题】:Is there a need to close resource if we use try-with-resource如果我们使用 try-with-resource 是否需要关闭资源 【发布时间】:2018-12-12 14:35:06 【问题描述】:

我在我的代码中使用 try-with-resource 块,想知道是否需要在方法结束时关闭资源或不需要?

try (S3Object object = s3.getObject(new GetObjectRequest(bucketName, key));
  BufferedReader br = new BufferedReader(new InputStreamReader(object.getObjectContent()));
  BufferedWriter bw = new BufferedWriter(new FileWriter(new File("output.txt"))))
  String line;

  while((line=br.readLine())!=null)
    bw.write(line);
    bw.newLine();
    bw.flush();
  

【问题讨论】:

不,如果你做对了就没有...... @deHaar,所以上面写的逻辑对吗?最后不需要 finally 阻塞 你也不需要bw.flush()。关闭 BufferedWriter(无论是自动还是手动)都会刷新它。 不,不需要关闭资源的finally 块。请参阅@ZhaoGang 给出的以下答案。我认为您必须在try-with 资源后面打开一个括号。 哪个资源? object(名字很糟糕,因为它并没有告诉我们太多关于该对象的信息)......或者你在体内使用的阅读器/作者? 【参考方案1】:

没有。

try-with-resources 语句确保每个资源在语句结束时关闭。任何实现 java.lang.AutoCloseable 的对象,包括所有实现 java.io.Closeable 的对象,都可以用作资源。

如果您使用的是 java 6 或更早版本:

在 Java SE 7 之前,您可以使用 finally 块来确保关闭资源,而不管 try 语句是正常完成还是突然完成。

更新:

您可以在 try-with-resources 语句中声明一个或多个资源。

正如您在代码中使用的那样。

【讨论】:

【参考方案2】:

不,你没有。我们来看一个try-catch-finallytry-with-resource的例子

Scanner scanner = null;
try 
    scanner = new Scanner(new File("test.txt"));
    while (scanner.hasNext()) 
        System.out.println(scanner.nextLine());
    
 catch (FileNotFoundException e) 
    e.printStackTrace();
 finally 
    if (scanner != null) 
        scanner.close();
    

这是您的常规try-catch-finally,您正在关闭finally 块中的扫描仪。现在让我们看看try-with-resource

try (Scanner scanner = new Scanner(new File("test.txt"))) 
    while (scanner.hasNext()) 
        System.out.println(scanner.nextLine());
    
 catch (FileNotFoundException fnfe) 
    fnfe.printStackTrace();

您不需要在这里关闭scanner,因为它会在try 块执行完毕后自行关闭。更多参考请访问blog

【讨论】:

【参考方案3】:

您不必关闭您在 try 子句中定义的资源。但是,根据您的示例,您在尝试的 body 中也有这个:

BufferedWriter bw = new BufferedWriter(new FileWriter(new File("output.txt"))))

并且您的代码没有关闭该资源。这是错误的(保持文件系统句柄打开很可能是真正的资源泄漏)。

换句话说:您可能希望将bw 添加到您的try-with-resources 子句中,因此它与S3Object object 的定义一起出现(参见here 的示例)。

【讨论】:

BufferedWriter 仅在 try only 子句中。 能否请您给我一些参考/代码,如果我使用 try-with-resource,我可以关闭多个资源,谢谢 try (S3Object object = s3.getObject(new GetObjectRequest(bucketName, key)); BufferedReader br = new BufferedReader(new InputStreamReader(object.getObjectContent())); BufferedWriter bw = new BufferedWriter(new FileWriter(new File("/tmp/output.txt")))) 抱歉,但我仍然很困惑 s3、br 和 bw 仅在 try 子句中。 它就像 try (clause ) body catch ... 所以,是的,您将要自动关闭的所有资源的定义从“body”移动到“clause”部分 让我们continue this discussion in chat.

以上是关于如果我们使用 try-with-resource 是不是需要关闭资源的主要内容,如果未能解决你的问题,请参考以下文章

Java进阶知识点3:更优雅地关闭资源 - try-with-resource语法

如何使用 Java7 try-with-resources 功能将资源作为参数传递

在 System.in 中使用 try-with-resources [重复]

try-with-resource机制的一个编译陷阱

谁在 close 方法中捕获异常?(try-with-resources)

使用 try-with-resources 读取和写入同一个文件