为什么发出终端操作后 Java close() 不流式传输?

2022-01-22 00:00:00 java-8 java java-stream

看完https://www.airpair.com/java/posts/spring-streams-memory-efficiency,我很想将结果从数据库中流出,但正如我与一位同事讨论的那样(cfr. 他在该文章中添加的评论),需要记住使用 try-with-resources构造以避免任何内存泄漏.

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. 为什么 Java 8 库在每次 终端操作(无需将流实例包装在 try-with-resources 中)?
  2. 如果适用,是否有将此功能添加到 Java 的任何计划,或者请求它是否有意义?
  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?

推荐答案

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

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.

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

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

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

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.

相关文章