繁体   English   中英

为什么在发出终端操作后没有Java close()流?

[英]Why doesn't Java close() stream after a terminal operation is issued?

在阅读了https://www.airpair.com/java/posts/spring-streams-memory-efficiency之后 ,我很想从数据库中传出结果,但正如我与同事讨论的那样(cfr。评论他补充说文章),需要记住使用try-with-resources构造来避免任何内存泄漏。

  1. 为什么Java 8库不会在每次终端操作后自行关闭流(不必在try-with-resources中包装流实例化)?
  2. 如果适用,是否有任何将此功能添加到Java的计划,或者请求它是否有意义?

因为需要显式资源释放的流实际上是一个非常不寻常的情况。 因此,我们选择不对所有流执行负担,这些内容仅对.01%的使用有价值。

我们制作了Stream Autocloseable,以便您可以根据需要从源中释放资源,但这是我们停止的地方,并且有充分的理由。

这样做不仅会使大多数用户自动负担他们不需要的额外工作,而且这也违反了一般原则:分配资源的人负责关闭资源。 你打电话的时候

BufferedReader reader = ...
reader.lines().op().op()...

是打开资源的人,而不是流库, 应该关闭它。 事实上,由于关闭在某个资源保持对象上调用访问器方法而产生的流有时会关闭底层对象,因此您可能不希望流为您关闭BufferedReader - 您可能希望它在之后保持打开状态呼叫。

如果要关闭资源,这也很容易:

try (BufferedReader reader = ...) {
    reader.lines().op()...
}

你可能正在以特定的方式使用流,所以它可能看起来“显而易见”流应该做什么 - 但是有比你更多的用例。 因此,我们不是满足于特定用例,而是从一般原则中接近它:如果您打开流,并且希望它关闭,请自行关闭它,但如果您没有打开它,则不能让您关闭。

我认为你将java.io.InputStreamjava.util.stream.Stream混合在一起,这是两个截然不同的概念。

try-with-resources适用于实现Autoclosable接口的对象,例如InputStream InputStream表示与IO相关的抽象数据源。

另一方面, java.util.stream.Stream<T>实现了函数式编程的概念,它代表了一种动态集合,它不一定是静态构建的,而是可以生成,因此可能是无限的。

Marko Topolnik(您链接的文章的作者)在本文中基本上做了什么,建议一种将IO源包装到java.util.stream.Stream 这是一个非常聪明的方法,但java.util.stream.Stream一般不用于此目的。

因为它们通常不打算与IO一起使用,所以它们没有理由在终端操作之后包括关闭


编辑

在你明确表示你实际上并没有将两者混淆之后(抱歉这样做),感谢这个答案 ,我发现你的确切例子在AutoCloseable文档中得到了回答(我自己强调了):

对于基类来说,实现AutoCloseable是可能的,并且实际上是常见的,即使并非所有子类或实例都将保留可释放的资源。 对于必须完全通用运行的代码,或者当已知AutoCloseable实例需要资源释放时,建议使用try-with-resources结构。 但是,当使用支持基于I / O和非I / O的表单的Stream等工具时,在使用非基于I / O的表单时,通常不需要try-with-resources块。

为什么Java 8库不会在每次终端操作后自行关闭流(不必在try-with-resources中包装流实例化)?

因为在终端操作期间或之前可能发生异常,并且您可能不希望终端操作关闭流。 如果您确实希望关闭流,则可以使用try-with-resource。

如果适用,是否有任何将此功能添加到Java的计划,或者请求它是否有意义?

这没有意义,见上面的答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM