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.