重学Java系列 – Try with Resources

1.概述

本文主要对Java 7中引入的try-with-resources进行简单的介绍,try-with-resources允许我们声明要在try块中声明使用的资源,并确保在执行该块之后资源将被关闭。声明的资源必须实现AutoCloseable接口。

2. 使用try-with-resources

简单地说,要自动关闭,必须在try中声明和初始化资源,如下所示:

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

3.用try-with-resources替换try-catch-finally

使用新的try-with-resources功能的简单而明显的方法是替换传统的和详细的try-catch-finally块。

让我们比较下面的代码示例

  • 典型的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();
    }
}
  • 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();
}

4. 自动关闭多个资源

通过使用分号分隔,可以在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.关闭实现AutoCloseable的自定义资源

如果想使用try-with-resources块自动关闭自定义资源,该类应实现CloseableAutoCloseable接口,并覆盖close方法:

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

6.资源关闭顺序

如果 我们在try-with-resources块定义了多个资源,首先定义的资源将最后关闭:

Resource 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:
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");
    }
}
演示:
private void orderOfClosingResources() throws Exception {
    try (AutoCloseableResourcesFirst af = new AutoCloseableResourcesFirst();
        AutoCloseableResourcesSecond as = new AutoCloseableResourcesSecond()) {
 
        af.doSomething();
        as.doSomething();
    }
}
控制台输出:
22:53:23.647 [main] DEBUG c.r.java.core.TryWithResourcesTest - Constructor -> AutoCloseableResources_First
22:53:23.649 [main] DEBUG c.r.java.core.TryWithResourcesTest - Constructor -> AutoCloseableResources_Second
22:53:23.649 [main] DEBUG c.r.java.core.TryWithResourcesTest - Something -> AutoCloseableResources_First
22:53:23.649 [main] DEBUG c.r.java.core.TryWithResourcesTest - Something -> AutoCloseableResources_Second
22:53:23.649 [main] DEBUG c.r.java.core.TryWithResourcesTest - Closed AutoCloseableResources_Second

7.catch 和 finally

try-with-resources块仍然可以拥有catchfinally块。和传统的try块一样工作。

8.小结

在本文中,我们讨论了

  • 如何使用try-with-resources
  • 如何替换try-catch-finallytry-with-resources
  • 使用AutoCloseable构建自定义资源
  • try-with-resources中关闭资源的顺序。

此示例的完整源代码在GitHub项目中。