java - 是否使用 try-with-resources 语句声明 Stream 有什么区别?

标签 java java-8 java-stream

在 Java 8 中,Stream(它是 AutoCloseable)不能被重用,一旦被消费或使用,流将被关闭。那么用 try-with-resources 语句声明的实用程序是什么?

带有 try-with-resources 语句的示例:

    public static void main(String[] args) throws IOException {

    try (Stream<Path> entries
            = Files.walk(Paths.get("."), 4, FileVisitOption.FOLLOW_LINKS)) {
        entries.forEach(x -> System.out.println(x.toAbsolutePath()));// the entries stream will be automatically closed at this point
        //..
        System.out.println("Still in the Try Block");
    } //The entries will be closed again because it is declared in the try-with-resources statement
}

这里是没有 try catch block 的相同示例

public static void main(String[] args) throws IOException {
        Stream<Path> entries = Files.walk(Paths.get("."), 4, FileVisitOption.FOLLOW_LINKS);
        entries.forEach(x -> System.out.println(x.toAbsolutePath()));// the entries stream will be automatically closed at this point
        System.out.println("Is there a risk of resources leak ?");
    }

哪个更安全?

经过一些回答后,我更新了我的代码以检查流是否已关闭:

这里是新代码:

public static void main(String[] args) throws IOException {

    resourceWithTry();
    resourceWithoutTry();
}

private static void resourceWithTry() throws IOException {
    try (Stream<Path> entries
            = Files.walk(Paths.get("."), 4, FileVisitOption.FOLLOW_LINKS).onClose(() -> System.out.println("The Stream is closed"))) {
        entries.forEach(x -> System.out.println(x.toAbsolutePath()));// the entries stream will be not automatically closed at this point
        System.out.println("Still in the Try Block");
    } //The entries will be closed again because it is declared in the try-with-resources statement
}

private static void resourceWithoutTry() throws IOException {
    Stream<Path> entries
            = Files.walk(Paths.get("."), 4, FileVisitOption.FOLLOW_LINKS).onClose(() -> System.out.println("Without Try: The Stream is closed"));
    entries.forEach(x -> System.out.println(x.toAbsolutePath()));// the entries stream will be not automatically closed at this point
    System.out.println("Still in the Try Block");
}

最佳答案

In Java 8, Stream (which is AutoCloseable) cannot be reused, once it is consumed or used, the stream will be closed.

不完全是。
Stream forEach()等终端操作不要关闭流。
它使流管道不再是可消耗的。
这是不同的。

Package java.util.stream description状态:

After the terminal operation is performed, the stream pipeline is considered consumed, and can no longer be used; if you need to traverse the same data source again, you must return to the data source to get a new stream.

它并没有说流已关闭。

所以在下面的代码中,AutoCloseable.close() Stream 的方法永远不会调用实例:

Stream<Path> entries = Files.walk(Paths.get("."), 4, FileVisitOption.FOLLOW_LINKS);
entries.forEach(x -> System.out.println(x.toAbsolutePath()));

那么是否总是需要关闭流? (使用显式 close() 调用或更好的 try-with-resources )

java.util.stream.Stream<T> javadocs 解释说几乎所有 Stream实例不需要用 AutoCloseable.close() 关闭使用后。
仅对 IO 流有效。

Streams have a close() method and implement AutoCloseable, but nearly all stream instances do not actually need to be closed after use. Generally, only streams whose source is an IO channel (such as those returned by Files.lines(Path, Charset)) will require closing. Most streams are backed by collections, arrays, or generating functions, which require no special resource management. (If a stream does require closing, it can be declared as a resource in a try-with-resources statement.)

在我们的例子中,您操纵 File s,所以关闭 channel 是有意义的。
通过使用 try-with-resources ,您可以避免可能发生的资源耗尽异常和错误。
如果在处理过程中出现任何错误或异常,资源可能会被释放。

关于java - 是否使用 try-with-resources 语句声明 Stream 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47108164/

相关文章:

java - 返回 JSON 的 Spring Restful Web 服务

java - Android 日程短信

java - Android 中的光标是从 0 还是 1 引用列?

java - 检查 map 中存在的值列表的最佳方法

java - Java 8 中的 PriorityBlockingQueue 流乱序

java-8 - 在 Java 8 中创建循环和无限范围整数的最惯用方法

java - 在简单登录中总是返回错误消息而不是成功消息

java - 使用java 8 Stream分割ArrayList并进行统计

java - 如何使用 Java 8 进行分组和收集?

java - 用 java 8 foreach 替换 for 循环来更新值