我希望实现Stream<E>
接口(我承认这是不必要的大接口),并添加了一个生成器方法foo()
。
public MyStream<E> implements Stream<E>, ExtendedStream<E> {
private final Stream<E> delegate;
public MyStream(final Stream<E> stream) {
this.delegate = stream;
}
// a sample Stream<E> method implementation
@Override
public <R> MyStream<R> map(Function<? super E, ? extends R> mapper) {
return new MyStream<>(this.delegate.map(mapper));
}
// the rest in the same way (skipped)
// a method from ExtendedStream<E>
@Override
public MyStream<E> foo() {
return new MyStream(this.delegate.......);
}
}
到目前为止,一切都很好。
long count = new MyStream(list.stream())
.map(i -> i * 10)
.foo()
.filter(i -> i > 100)
.count();
我对Closeable
的{{1}}行为有疑问。 Stream
的文档中介绍了有关关闭(格式化我的)的信息:
流具有
Stream
方法并实现BaseStream.close()
,但是实际上几乎所有流实例在使用后都不需要关闭。通常,只有源是IO通道的流(例如AutoCloseable
返回的流)才需要关闭。
关闭Stream的唯一方法是Files.lines(Path, Charset))
或flatMap
。
在 Eclipse Oxygen 中的对象实例化带有以下警告:
资源泄漏:“
close
”从未关闭
IntelliJIdea 2018.1.5 不能重现此问题。我略过的相关问题是here和here。我了解<unassigned Closeable value>
或Closeable
的{{1}}问题,但是,我对Streams感到困惑。
我不喜欢调用私有构造方法的静态方法File
。
答案 0 :(得分:3)
In Java 7 the description of AutoCloseable
是
“ ... 必须关闭 ...”
而in Java 8 the description在语义上已更改为
“ ... 可以保存资源(例如文件或套接字句柄)...”
在Eclipse中,对于未关闭的所有Closeable
和AutoCloseable
实例,资源泄漏警告均独立于Java版本显示(在您的示例中就是这种情况)。参见Eclipse help:
考虑了实现接口
java.io.Closeable
(自JDK 1.5起)和java.lang.AutoCloseable
(自JDK 1.7起)的类以表示外部资源,应使用方法{{ 1}},当不再需要它们时。
根据更改后的Javadoc描述,我希望在Java 8或更高版本中,未关闭的close()
只会发出潜在资源泄漏警告,而不是资源泄漏 em>警告。 Eclipse JDT开发人员Stephan Herrmann,explains in his answer why he doesn't think this is a good idea。
作为Java 8或更高版本的解决方法,将AutoCloseable
添加到不必关闭@SuppressWarnings("resource")
的那些地方。
答案 1 :(得分:3)
作为JSR 335工作的一部分,JRE库通过引入java.util.Stream
而发展,同时在java.nio
等地方利用了新概念。在此期间,JSR 335专家组与Eclipse团队进行了磋商,以讨论以下冲突:
诸如ecj之类的工具希望在程序员忘记关闭抗GC(GCR)资源(例如FileInputStream
)时发出信号。
图书馆团队计划将java.util.Stream
设为AutoCloseable
的子类型,以便在{-{1}}可以可能由GCR资源支持。仍然,默认假设应该是j.u.Stream
的实例不不需要进行j.u.Stream
调用。
仍然,close()
中的某些方法返回java.nio
的{{1}} 要求。
EG和Eclipse同意,找不到简单的解决方案,这样仅通过查看可关闭对象的类型,任何工具都可以准确识别 >是否需要关闭。这是由于各种资源在多个级别上包装其他资源的复杂性。特别是类型j.u.Stream
不能表示实例是否由GCR资源支持。
为获得清晰的结果,还需要使用类型注释系统(使用JSR 308),以使用精确的静态分析所需的信息来丰富类型系统。据我所知,这种方法直到今天才得以实现。
作为一种折衷,建议像Eclipse这样的工具实现者按照以下方式对启发式编码:
通常,所有close()
类型的实例都应关闭。
以下已知类型集将从分析中排除,因为通常 不需要关闭:j.u.Stream
和AutoCloseable
。
作为该异常的一个例外,已知java.util.Stream
中某些返回Stream的静态方法 require 关闭。
讨论基本上发生在lambda-libs-spec-observers邮件列表上的以下两个帖子之间:
历史这么多。
2013年的讨论未考虑{Int,Long,Double}Stream
的自定义实现。 Eclipse假定没有关于那些实现的特定知识。最好是,如果不是这样,该工具将决定是否需要close()的偏见,但是如果实现者(在java.nio
处)有办法表明,此类的实例是否需要关闭或不。但是,迄今为止的实现者没有办法表达这一点。
由于缺乏完整而精确的选择,我们可以讨论扩展启发式方法的集合,这样,不仅j.u.Stream
系列中的已知类型集,而且还包括其所有子类型 >从分析中排除,并被认为是GC友好的。显然,这种方法会增加假阴性(分析遗漏的错误)的风险。
如霍尔格的答案所建议的那样,将警告标记为“潜在泄漏”将是令人困惑的,因为在流分析中,“潜在”一词通常应表示在整个程序中(但不是全部)发生的行为。
截止到今天,可用的选项是:
在使用MyStream
的任何地方使用j.u.Stream
(首选)
降低此特定问题的严重性(如果使用@SuppressWarnings("resource")
的使用范围太广而无法使用第一种选择)。