ZetCode

Java AutoCloseable

最后修改于 2025 年 4 月 2 日

AutoCloseable 接口是 Java 资源管理系统的一个基本组成部分,在 Java 7 中引入。它通过 try-with-resources 语句实现自动资源管理,确保资源的正确清理。

在本教程中,我们将探讨如何使用 AutoCloseable 安全有效地管理文件、数据库连接和网络套接字等资源。我们将介绍内置实现和自定义资源类。

理解 AutoCloseable

AutoCloseable 是一个只有一个方法的接口

AutoCloseable.java
public interface AutoCloseable {

    void close() throws Exception;
}

任何实现 AutoCloseable 的类都可以与 try-with-resources 一起使用。当 try 块退出时,无论正常退出还是异常退出,都会自动调用 close() 方法。

Try-With-Resources 基础

try-with-resources 语句自动关闭实现 AutoCloseable 的资源。 这是基本语法

TryWithResources.java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

void readFile(String path) throws IOException {

    try (BufferedReader br = new BufferedReader(new FileReader(path))) {

        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    }
}

即使发生异常,BufferedReader 也会在 try 块完成后自动关闭。 这消除了手动 finally 块的需要。

多个资源

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

MultipleResources.java
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipInputStream;

void copyZipFile(File source, File target) throws IOException {

    try (InputStream in = new FileInputStream(source);
         OutputStream out = new FileOutputStream(target);
         ZipInputStream zipIn = new ZipInputStream(in)) {
        
        byte[] buffer = new byte[1024];
        int length;
        while ((length = zipIn.read(buffer)) > 0) {
            out.write(buffer, 0, length);
        }
    }
}

资源以声明的相反顺序关闭。 如果任何资源无法关闭,其他资源仍会尝试关闭。

创建自定义 AutoCloseable 资源

您可以为自定义资源创建自己的 AutoCloseable 实现

CustomResource.java
class DatabaseConnection implements AutoCloseable {

    private boolean isOpen = true;
    
    public void executeQuery(String query) {
        if (!isOpen) {
            throw new IllegalStateException("Connection closed");
        }
        System.out.println("Executing: " + query);
    }
    
    @Override
    public void close() {
        if (isOpen) {
            System.out.println("Closing database connection");
            isOpen = false;
        }
    }
}

void useDatabase() {
    try (DatabaseConnection conn = new DatabaseConnection()) {
        conn.executeQuery("SELECT * FROM users");
    }
}

这个自定义 DatabaseConnection 演示了正确的资源清理模式。 close 方法是幂等的(可以安全地多次调用)。

被抑制的异常

当 try 块中和资源关闭期间都发生异常时,关闭异常会被“抑制”并附加到主要异常

SuppressedExceptions.java
class FailingResource implements AutoCloseable {

    @Override
    public void close() throws Exception {
        throw new Exception("Error during close");
    }
    
    public void use() throws Exception {
        throw new Exception("Error during use");
    }
}

void demonstrateSuppressed() {

    try (FailingResource res = new FailingResource()) {
    
        res.use();
    } catch (Exception e) {
    
        System.out.println("Caught: " + e.getMessage());

        for (Throwable t : e.getSuppressed()) {
            System.out.println("Suppressed: " + t.getMessage());
        }
    }
}

此示例显示了如何访问在资源清理期间发生的被抑制的异常。

AutoCloseable vs Closeable

Closeable 是一个类似于 AutoCloseable 的接口,但出现的时间更早。 主要区别:

CloseableComparison.java
interface Closeable extends AutoCloseable {
    void close() throws IOException; // More specific exception
}

最佳实践

使用 AutoCloseable 时

来源

Java AutoCloseable 文档

本教程涵盖了 Java AutoCloseable 接口和 try-with-resources 语句的基本方面,以便在 Java 应用程序中进行适当的资源管理。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 我从 2007 年开始撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有Java教程