Java 8 Stream实例是否应该始终是close()'?


12

Javadoc的看法

流具有BaseStream.close()方法并实现AutoCloseable,但实际上几乎所有流实例在使用后实际上都不需要关闭。通常,只有源是IO通道的流(例如,由Files.lines(Path,Charset)返回的流)才需要关闭。大多数流都由集合,数组或生成函数支持,不需要特殊的资源管理。(如果流确实需要关闭,则可以在try-with-resources语句中将其声明为资源。)

“几乎所有”和“通常”是模糊的-如果您正在编写库,并且要从该Stream的用户中提取Stream的源,那么无论如何,您总是必须问自己一个问题-“我应该关闭这个?” IO支持的流需要关闭,因为终端操作不会调用close,所以有效地我总是必须记住/记录我的Stream的来源,或者我总是必须这样close做。

我猜想,最明智的选择是不从方法中返回Streams或接受Stream参数,这是JDK团队中某些人所认同的观点。考虑到Streams的实用性,我发现这过于局限。

关闭Streams的最佳做法是什么?我在网上寻找了一些JDK人员的答案,这些人员通常都积极参与类似的社区问题,但是没有发现任何相关的内容。


不是Java开发人员,但我会使用以下规则:-如果将流作为参数传递,则记录调用者必须在需要时关闭该流;-如果流是从函数返回给您的,则假定您需要关闭它。
Bart van Ingen Schenau 2015年

Answers:


6

如您所说,在Java中,您需要确切地知道谁负责释放哪个资源,因此您可以放入适当的try-catch-constructs,try-with-resources或以某种方式委派该任务。

您唯一可以依靠GC清理的是100%的纯内存。
如果可能还有其他资源混用,那么您唯一可以合理做的就是简单地安全使用它。


那么基本上close是唯一安全的选择吗?我想问题是,如何避免每次Stream都易于使用时使代码看起来过于丑陋。
RuslanD

1
是的,如果有可能被非内存资源,唯一安全的事情是假设存在。即使Java非常不适用于非GC的资源,也无法解决。
Deduplicator

因此,如果它只是两个集合之间的流(纯内存),则不必关闭它吗?
Amalgovinus

@Amalgovinus正确
Brad Cupit

5

就“最佳实践”而言,我认为对返回“资源流”的方法使用命名约定是个好主意。

如果必须close()编辑流,请调用factory方法open()openStream()stream()遵循SDK建立的约定,构造临时流的调用方法。始终将javadoc放在方法上,以警告客户端他们必须close()这样做。

public interface StreamingServer<RECORD> {
    /** 
     * Return a memory-efficient record stream from {@code source}.
     * Clients <em>must</em> call {@link Stream#close} to dispose the
     * stream.
     */
    Stream<RECORD> openStream(URI source) throws IOException;
}

我希望SDK开发者不要选择AutoCloseable使用基本流类。一个ResourceStream简单实现的独特子类型AutoCloseable会使不同的合同变得显而易见。然后,您将无法关闭Stream不需要的容器,并且可能会ResourceStream在静态分析工具中检测到潜在的管理不善。

根据您的代码库的需求(以及您在代码审阅中强制执行约定的能力),您可以自己建立一个需要紧密的流子类。或者,如果您要构建自己的静态分析工具,则可以使用方法注释直接标记托管资源。

@RequiresClose
Stream<RECORD> openStream(URI source) throws IOException { ... }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.