我是否需要为所有 writers/readers 保留变量以手动关闭它们?

Do I need to keep variables for all writers/readers to close them all manually?

考虑这个例子:

public class FileAppender implements AutoCloseable {
    private final FileWriter fileWriter;
    private final BufferedWriter bufferedWriter;

    public FileAppender(String fileName) throws IOException {
        fileWriter = new FileWriter(fileName, true)
        bufferedWriter = new BufferedWriter(fileWriter);
    }

    public void appendLine(String line) throws IOException {
        bufferedWriter.write(line + "\n");
    }

    @Override
    public void close() throws Exception {
        bufferedWriter.close();
        fileWriter.close();
    }
}

这里我们保留一个未使用的FileWriter作为class的成员,这样我们以后可以手动关闭它。网上有很多教程展示了这样的示例,其中多个流被手动关闭。

我们可以更简洁地实现相同的 class:

public class FileAppender implements AutoCloseable {
    private final BufferedWriter writer;

    public FileAppender(String fileName) throws IOException {
        writer = new BufferedWriter(new FileWriter(fileName, true));
    }

    public void appendLine(String line) throws IOException {
        writer.write(line + "\n");
    }

    @Override
    public void close() throws Exception {
        writer.close();
    }
}

同样适用于 FileReaderBufferedReader 的用法。

以上两种实现方式有区别吗?

使用 BufferedWriter,具体来说,您可以在 BufferedWriter 上使用 close,它会在基础 FileWriter 上调用 close

但是,据我所知,这没有记录,并且不需要 Writer 实现包装其他 Writer(和同样,流)。我很偏执,倾向于明确地关闭事物(与打开它们的顺序相反)。

您可以在 BufferedWriter 源代码中看到关闭操作(此示例来自 JDK 11.0.1),但您必须仔细查看:

public void close() throws IOException {
    synchronized (lock) {
        if (out == null) {
            return;
        }
        try (Writer w = out) {
            flushBuffer();
        } finally {
            out = null;
            cb = null;
        }
    }
}

注意 try-with-resources 到 auto-close out 的用法(通过 w)。