"resource leak: stream is never closed" 的背景

Background of "resource leak: stream is never closed"

给定一个使用流的 Java 函数:

List<String> function(List<String> input) {
    Stream<String> a = input.parallelStream();
    Stream<String> b = a.map(c -> c.toString());
    return b.collect(Collectors.toList());
}

现在,我想控制是否通过参数进行映射。 Eclipse/the 编译器给我一个警告:资源泄漏:'a' 从未关闭

List<String> function(List<String> input, boolean doMap) {
    Stream<String> a = input.parallelStream(); // Resource leak: 'a' is never closed
    Stream<String> b = doMap ? a.map(c -> c.toString()) : a;
    return b.collect(Collectors.toList());
}

我可以使用 try-with-resources 语句解决这个问题:

List<String> function(List<String> input, boolean doMap) {
    try (Stream<String> a = input.parallelStream()) {
        Stream<String> b = doMap ? a.map(c -> c.toString()) : a;
        return b.collect(Collectors.toList());
    }
}

我的问题是:当我使用流而不是 for 循环时,为什么会出现资源泄漏?如果我只是选择性地添加映射步骤,为什么会出现资源泄漏? (为什么第一个版本的函数没有资源泄漏?)有条件地组合处理流是否“危险”?我错过了什么?

我总结一下@Nikolas 换句话说再次回答:Java没有问题,但是“问题”(如果你想在all) 是变量。如果变量被声明为实现 AutoCloseable 的类型(并且 Stream 实现),Eclipse 显然会在此处报告警告,如果它没有找到对 [=12= 的调用,则它不会被关闭].

由于此错误与 Eclipse 相关,因此其他检查工具很可能不会对此失败,并且不需要“修复”即可通过此类检查。

根据我的理解,这显示了 Java 的一个基本问题,即它不会在不再需要时立即释放变量上的对象,而是在某个随机点释放它。有了资源,那就失败了。因此,资源必须由开发人员手动跟踪,在哪里关闭它们以及手动关闭它们。 Java 运行时将(假设)必须实现类似于 C++ 的 std::auto_ptr 的方法,那么这就没有必要了,如果删除了对资源的最后引用,则可以关闭它。但它不像 java "thinks".