try-with-resources使用指南

1. 概述

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

声明的资源需要实现_自动关闭接口_。

2. 使用_资源Try代码块_

简而言之,要自动关闭,必须在 try 中声明和初始化资源:

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

3. 用_资源的try_替换_try-_finally

使用新的“try_资源_”功能的简单而明显的方法是替换传统的_冗长的“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_的新的超级简洁解决方案:

复制代码

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

复制代码

下面是进一步探索_扫描程序_类的位置。

4. 使用_多个资源t_ry-with-resources 块

我们可以在 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. _具有自动关闭功能的_自定义资源

若要构造将由 try-with-resources 块正确处理的自定义资源,该类应实现 Closeable 或 AutoCloseable 接口并重写 close 方法:

复制代码

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

复制代码

6. 资源关闭顺序

首先定义/获取的资源将最后关闭。让我们看一下此行为的示例:

资源 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");
}

}

复制代码

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

}

复制代码

输出:

复制代码

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

复制代码

7.catch__和_finally_

_try资源_块仍然可以具有_catch_和_finally_块,其工作方式与传统的_try_块相同。

8. Java 9 – 有效的finally变量

在Java 9之前,我们只能在_try-with-resources_块中使用新变量:

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

如上所示,这在声明多个资源时尤其冗长。从 Java 9 开始,作为 JEP 213 的一部分,我们现在可以在_资源try_块中使用finally甚至有效的_finally_变量:

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

简而言之,如果变量在第一次赋值后没有更改,即使它没有明确标记为 final,它实际上是 _final_。

如上所示,scanner 变量被显式声明为 _final_,因此我们可以将其与 try-with-resources 块一起使用。尽管_编写器_变量不是_显式 final_,但它在第一次赋值后不会更改。因此,我们也可以使用_编写器_变量。

9. 结论

在本文中,我们讨论了如何使用 try-with-resources 以及如何用 try-with-resources 替换 _try_、_catch_,_finally_。

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