Java – Try with Resources – Java – 使用资源进行尝试

最后修改: 2015年 12月 25日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Support for try-with-resources — introduced in Java 7 — allows us to declare resources to be used in a try block with the assurance that the resources will be closed after the execution of that block.

try-with-resources的支持–在Java 7中引入–允许我们声明在try块中使用的资源,并保证在执行该块后资源将被关闭。

The resources declared need to implement the AutoCloseable interface.

声明的资源需要实现AutoCloseable接口。

2. Using try-with-resources

2.使用尝试-资源

Simply put, to be auto-closed, a resource has to be both declared and initialized inside the try:

简单地说,要想自动关闭,一个资源必须在try内被声明和初始化。

try (PrintWriter writer = new PrintWriter(new File("test.txt"))) {
    writer.println("Hello World");
}

3. Replacing trycatch-finally With try-with-resources

3.用trycatch-finally代替try-with-resources

The simple and obvious way to use the new try-with-resources functionality is to replace the traditional and verbose try-catch-finally block.

使用新的try-with-resources功能的简单而明显的方法是取代传统的、冗长的try-catch-finally块。

Let’s compare the following code samples.

让我们比较一下下面的代码样本。

The first is a typical try-catch-finally block:

第一个是典型的try-catch-finally块。

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();
    }
}

And here’s the new super succinct solution using try-with-resources:

这里是使用try-with-resources的新的超级简洁的解决方案。

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

Here’s where to further explore the Scanner class.

这里是进一步探索Scanner的地方。

4. try-with-resources With Multiple Resources

4.尝试使用资源与多个资源

We can declare multiple resources just fine in a try-with-resources block by separating them with a semicolon:

我们可以在一个try-with-resources块中声明多个资源,只要用分号将它们分开就可以了。

try (Scanner scanner = new Scanner(new File("testRead.txt"));
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
    while (scanner.hasNext()) {
	writer.print(scanner.nextLine());
    }
}

5. A Custom Resource With AutoCloseable

5.一个带有AutoCloseable的自定义资源

To construct a custom resource that will be correctly handled by a try-with-resources block, the class should implement the Closeable or AutoCloseable interfaces and override the close method:

要构建一个能被try-with-resources块正确处理的自定义资源,该类应实现CloseableAutoCloseable接口并重写close方法。

public class MyResource implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("Closed MyResource");
    }
}

6. Resource Closing Order

6.资源关闭令

Resources that were defined/acquired first will be closed last. Let’s look at an example of this behavior:

先定义/获得的资源将被最后关闭。让我们看看这种行为的一个例子。

Resource 1:

资源1:

public class AutoCloseableResourcesFirst implements AutoCloseable {

    public AutoCloseableResourcesFirst() {
        System.out.println("Constructor -> AutoCloseableResources_First");
    }

    public void doSomething() {
        System.out.println("Something -> AutoCloseableResources_First");
    }

    @Override
    public void close() throws Exception {
        System.out.println("Closed AutoCloseableResources_First");
    }
}

Resource 2:

资源2:

public class AutoCloseableResourcesSecond implements AutoCloseable {

    public AutoCloseableResourcesSecond() {
        System.out.println("Constructor -> AutoCloseableResources_Second");
    }

    public void doSomething() {
        System.out.println("Something -> AutoCloseableResources_Second");
    }

    @Override
    public void close() throws Exception {
        System.out.println("Closed AutoCloseableResources_Second");
    }
}

Code:

代码:

private void orderOfClosingResources() throws Exception {
    try (AutoCloseableResourcesFirst af = new AutoCloseableResourcesFirst();
        AutoCloseableResourcesSecond as = new AutoCloseableResourcesSecond()) {

        af.doSomething();
        as.doSomething();
    }
}

Output:

产出:

Constructor -> AutoCloseableResources_First
Constructor -> AutoCloseableResources_Second
Something -> AutoCloseableResources_First
Something -> AutoCloseableResources_Second
Closed AutoCloseableResources_Second
Closed AutoCloseableResources_First

构造函数 -> AutoCloseableResources_First
构造器 -> AutoCloseableResources_Second
某物 -> AutoCloseableResources_First

某物 -> AutoCloseableResources_Second
关闭的 AutoCloseableResources_Second
关闭自动关闭的资源_第一个

7. catch and finally

7.catchfinally

A try-with-resources block can still have the catch and finally blocks, which will work in the same way as with a traditional try block.

一个try-with-resources仍然可以有catchfinally,其工作方式与传统try块相同。

8. Java 9 – Effectively Final Variables

8.Java 9 – 有效的最终 变量

Before Java 9, we could only use fresh variables inside a try-with-resources block:

在Java 9之前,我们只能在try-with-resources 块内使用新鲜变量。

try (Scanner scanner = new Scanner(new File("testRead.txt")); 
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { 
    // omitted
}

As shown above, this was especially verbose when declaring multiple resources. As of Java 9 and as part of JEP 213, we can now use final or even effectively final variables inside a try-with-resources block:

如上所示,在声明多个资源时,这一点特别啰嗦。从 Java 9 开始,作为 JEP 213 的一部分,我们现在可以在 try-with-resources 块内使用 final 或甚至 effective final 变量。

final Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))
try (scanner;writer) { 
    // omitted
}

Put simply, a variable is effectively final if it doesn’t change after the first assignment, even though it’s not explicitly marked as final.

简单地说,如果一个变量在第一次赋值后没有变化,那么它实际上就是最终变量,尽管它没有明确地被标记为最终

As shown above, the scanner variable is declared final explicitly, so we can use it with the try-with-resources block. Although the writer variable is not explicitly final, it doesn’t change after the first assignment. So, we can to use the writer variable too.

如上所示,scanner 变量被明确声明为final ,所以我们可以在try-with-resources 块中使用它。尽管writer 变量没有明确的final,它在第一次赋值后并没有改变。所以,我们也可以使用writer变量。

9. Conclusion

9.结论

In this article, we discussed how to use try-with-resources and how to replace try, catch, and finally with try-with-resources.

在这篇文章中,我们讨论了如何使用try-with-resources,以及如何用try-with-resources替换trycatchfinally

We also looked at building custom resources with AutoCloseable and the order in which resources are closed.

我们还研究了用AutoCloseable构建自定义资源以及资源关闭的顺序。

The complete source code for the example is available in this GitHub project.

该示例的完整源代码可在该GitHub项目中获取。