流上的终端操作是否会关闭源?

2022-09-02 03:56:34

请考虑以下代码:

Path directory = Paths.get(/* some directory */);
Files.list(directory).forEach(System.out::println);

终端操作(如 )是否关闭已打开的基础文件?forEach

請參閱 files.list 的 javadoc 的相關部分:

返回的流封装了目录流。如果需要及时处置文件系统资源,则应使用资源试用构造来确保在流操作完成后调用流的 close 方法。

如果它不调用 ,那么在生成可维护代码的同时调用它的最佳替代方案是什么?Stream.close()


答案 1

终端运营商不会自动关闭流。请考虑以下代码:

Stream<Path> list = Files.list(directory).onClose(() -> System.out.println("Closed"));
list.forEach(System.out::println);

这不会打印“已关闭”。

但是,以下内容会打印“已关闭”:

try (Stream<Path> list = Files.list(directory).onClose(() -> System.out.println("Closed"))) {
    list.forEach(System.out::println);
}

因此,最好的方法是使用资源试用机制。


答案 2

因此,快速检查显示不会关闭:forEachDirectoryStream

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Consumer;
import java.util.stream.Stream;

/**
 * Created for http://stackoverflow.com/q/27381329/1266906
 */
public class FileList {
    public static void main(String[] args) {
        Path directory = Paths.get("C:\\");
        try {
            Stream<Path> list = Files.list(directory).onClose(() -> System.out.println("Close called"));
            list.forEach(System.out::println);
            // Next Line throws "java.lang.IllegalStateException: stream has already been operated upon or closed" even though "Close called" was not printed
            list.forEach(System.out::println);
        } catch (IOException | IllegalStateException e) {
            e.printStackTrace();  // TODO: implement catch
        }

        // The mentioned try-with-resources construct
        try (Stream<Path> list = Files.list(directory)) {
            list.forEach(System.out::println);
        } catch (IOException | IllegalStateException e) {
            e.printStackTrace();  // TODO: implement catch
        }

        // Own helper-method
        try {
            forEachThenClose(Files.list(directory), System.out::println);
        } catch (IOException | IllegalStateException e) {
            e.printStackTrace();  // TODO: implement catch
        }
    }

    public static <T> void forEachThenClose(Stream<T> list, Consumer<T> action) {
        try {
            list.forEach(action);
        } finally {
            list.close();
        }
    }
}

我看到了两个提出的缓解措施:

  1. 使用 JavaDoc 中所述的 try-with-resourcesFiles.list
  2. 编写你自己的帮助程序方法,它利用了 final-block

哪个更易于维护可能取决于您需要多少个帮助程序方法。


推荐