简体   繁体   English

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

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

After reading https://www.airpair.com/java/posts/spring-streams-memory-efficiency , I am tempted to stream results out of a database, but as I discussed with a colleague (cfr. comment he added to that article), one needs to remember to use the try-with-resources construct to avoid any memory leaks. 在阅读了https://www.airpair.com/java/posts/spring-streams-memory-efficiency之后 ,我很想从数据库中传出结果,但正如我与同事讨论的那样(cfr。评论他补充说文章),需要记住使用try-with-resources构造来避免任何内存泄漏。

  1. Why doesn't the Java 8 library take care of closing streams itself after each terminal operation (without having to wrap the stream instantiation in a try-with-resources)? 为什么Java 8库不会在每次终端操作后自行关闭流(不必在try-with-resources中包装流实例化)?
  2. If applicable, are there any plans for this functionality to be added to Java, or would it make sense to request it? 如果适用,是否有任何将此功能添加到Java的计划,或者请求它是否有意义?

Because streams that require explicit resource release is actually a pretty unusual case. 因为需要显式资源释放的流实际上是一个非常不寻常的情况。 So we chose not to burden all stream execution with something that is only valuable for .01% of usages. 因此,我们选择不对所有流执行负担,这些内容仅对.01%的使用有价值。

We made Stream Autocloseable so that you can release resources from the source if you want to, but this is where we stopped, and for a good reason. 我们制作了Stream Autocloseable,以便您可以根据需要从源中释放资源,但这是我们停止的地方,并且有充分的理由。

Not only would doing this automagically burden the majority of users with extra work that they don't need, but this would also violate a general principle: he who allocates the resource is responsible for closing the resource. 这样做不仅会使大多数用户自动负担他们不需要的额外工作,而且这也违反了一般原则:分配资源的人负责关闭资源。 When you call 你打电话的时候

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

you are the one opening the resource, not the stream library, and you should close it. 是打开资源的人,而不是流库, 应该关闭它。 In fact, since closing a stream resulting from calling an accessor method on some resource-holding object will sometimes close the underlying object, you probably don't want the stream closing the BufferedReader for you -- you might want it to stay open after the call. 事实上,由于关闭在某个资源保持对象上调用访问器方法而产生的流有时会关闭底层对象,因此您可能不希望流为您关闭BufferedReader - 您可能希望它在之后保持打开状态呼叫。

If you want to close the resource, this is easy too: 如果要关闭资源,这也很容易:

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

You're probably using streams in a particular way, so it probably seems "obvious" what streams should do -- but there are more use cases out there than yours. 你可能正在以特定的方式使用流,所以它可能看起来“显而易见”流应该做什么 - 但是有比你更多的用例。 So rather than catering to specific use cases, we approached it from the general principle: if you opened the stream, and you want it closed, close it yourself, but if you didn't open it, it's not for you to close. 因此,我们不是满足于特定用例,而是从一般原则中接近它:如果您打开流,并且希望它关闭,请自行关闭它,但如果您没有打开它,则不能让您关闭。

I think you're mixing java.io.InputStream with java.util.stream.Stream , which are two very very different concepts. 我认为你将java.io.InputStreamjava.util.stream.Stream混合在一起,这是两个截然不同的概念。

try-with-resources works on objects implementing the Autoclosable interface, such as InputStream s. try-with-resources适用于实现Autoclosable接口的对象,例如InputStream InputStream s represent an abstract source of data related to IO . InputStream表示与IO相关的抽象数据源。

java.util.stream.Stream<T> on the other hand, implements a concept from functional programming, which represents a kind of a dynamic collection which is not necessarily statically built, but can rather be generated, and consequently potentially infinite. 另一方面, java.util.stream.Stream<T>实现了函数式编程的概念,它代表了一种动态集合,它不一定是静态构建的,而是可以生成,因此可能是无限的。

What Marko Topolnik (the author of the article you linked to) essentially does in the article, is suggest a way to wrap an IO source into a java.util.stream.Stream . Marko Topolnik(您链接的文章的作者)在本文中基本上做了什么,建议一种将IO源包装到java.util.stream.Stream This is quite a clever approach, but java.util.stream.Stream s are not in general intended for this purpose. 这是一个非常聪明的方法,但java.util.stream.Stream一般不用于此目的。

Because they are not in general intended for use with IO , there is no reason for them to include closing after terminal operations. 因为它们通常不打算与IO一起使用,所以它们没有理由在终端操作之后包括关闭


EDIT : 编辑

After you've clarified that you hadn't in fact mixed up the two (sorry for assuming so), thanks to this answer , I found that your exact example is answered in the documentation of AutoCloseable (emphasis added by myself): 在你明确表示你实际上并没有将两者混淆之后(抱歉这样做),感谢这个答案 ,我发现你的确切例子在AutoCloseable文档中得到了回答(我自己强调了):

It is possible, and in fact common, for a base class to implement AutoCloseable even though not all of its subclasses or instances will hold releasable resources. 对于基类来说,实现AutoCloseable是可能的,并且实际上是常见的,即使并非所有子类或实例都将保留可释放的资源。 For code that must operate in complete generality, or when it is known that the AutoCloseable instance requires resource release, it is recommended to use try-with-resources constructions. 对于必须完全通用运行的代码,或者当已知AutoCloseable实例需要资源释放时,建议使用try-with-resources结构。 However, when using facilities such as Stream that support both I/O-based and non-I/O-based forms, try-with-resources blocks are in general unnecessary when using non-I/O-based forms. 但是,当使用支持基于I / O和非I / O的表单的Stream等工具时,在使用非基于I / O的表单时,通常不需要try-with-resources块。

Why doesn't the Java 8 library take care of closing streams itself after each terminal operation (without having to wrap the stream instantiation in a try-with-resources)? 为什么Java 8库不会在每次终端操作后自行关闭流(不必在try-with-resources中包装流实例化)?

Because an exception may occur during or before the terminal operation, and because you may not want the terminal operation to close the stream. 因为在终端操作期间或之前可能发生异常,并且您可能不希望终端操作关闭流。 You can use try-with-resource if you definitely want the stream to close. 如果您确实希望关闭流,则可以使用try-with-resource。

If applicable, are there any plans for this functionality to be added to Java, or would it make sense to request it? 如果适用,是否有任何将此功能添加到Java的计划,或者请求它是否有意义?

It would not make sense, see answer above. 这没有意义,见上面的答案。

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

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