简体   繁体   中英

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.

  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)?
  2. If applicable, are there any plans for this functionality to be added to Java, or would it make sense to request it?

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.

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.

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.

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.

try-with-resources works on objects implementing the Autoclosable interface, such as InputStream s. InputStream s represent an abstract source of data related to 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.

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 . This is quite a clever approach, but java.util.stream.Stream s are not in general intended for this purpose.

Because they are not in general intended for use with IO , there is no reason for them to include closing after terminal operations.


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):

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. 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. 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.

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)?

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.

If applicable, are there any plans for this functionality to be added to Java, or would it make sense to request it?

It would not make sense, see answer above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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