当前位置: 首页 > 知识库问答 >
问题:

为什么Java在发出终端操作后不关闭()流?

微生弘
2023-03-14

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

  1. 为什么Java 8库不负责在每次终端操作后关闭流本身(而不必将流实例化包装在资源试用中)

共有3个答案

欧阳学真
2023-03-14

为什么Java 8库不负责在每次终端操作后关闭流本身(而不必将流实例化包装在资源试用中)?

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

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

这毫无意义,请参阅上面的答案。

李和裕
2023-03-14

我认为你在混合java。io。使用java的InputStream。util。流动流是两个非常不同的概念。

try-with-resources用于实现自动关闭接口的对象,例如InputStream。InputStream代表与IO相关的抽象数据源。

<代码>java。util。流动流动

Marko Topolnik(您链接到的文章的作者)在文章中主要做的是建议一种将IO源代码包装到java.util.stream.Stream中的方法。这是一种非常聪明的方法,但是java.util.stream.Stream通常不是用于此目的的。

由于它们通常不用于IO,因此它们没有理由包括终端操作后的关闭。

编辑:

在您澄清事实上并没有混淆这两者之后(很抱歉这样假设),由于这个答案,我发现您的确切示例在自动关闭的文档中得到了回答(重点由我自己添加):

基类实现AutoCloseable是可能的,事实上也是常见的,即使不是它的所有子类或实例都包含可释放的资源。对于必须完全通用地运行的代码,或者当知道AutoCloseable实例需要资源释放时,建议使用资源尝试结构。但是,当使用同时支持基于I/O和非基于I/O的表单的工具(如Stream)时,使用非基于I/O的表单时,资源尝试块通常是不必要的。

沈华晖
2023-03-14

因为需要显式资源释放的流实际上是一种非常罕见的情况。因此,我们选择不让所有流执行都负担一些仅对其有价值的内容。01%的用法。

我们使流可以自动关闭,以便您可以根据需要从源代码中释放资源,但这就是我们停止的地方,这是一个很好的理由。

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

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

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

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

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

您可能以特定的方式使用流,因此流应该做什么似乎“显而易见”——但是比您的用例更多。因此,我们不是迎合特定的用例,而是从一般原则来处理它:如果您打开了流,并且希望关闭它,请自行关闭它,但如果您没有打开它,则不适合您关闭。

 类似资料:
  • 问题内容: 阅读https://www.airpair.com/java/posts/spring-streams-memory- efficiency后 ,我很想将结果从数据库中流式传输,但是正如我与同事讨论的那样(他在评论中补充)文章),需要记住使用try-with- resources构造以避免任何内存泄漏。 为什么Java 8库在每次终端操作后都不负责关闭流本身(而不必将流实例化包装在tr

  • 问题内容: 考虑以下代码: 终端操作(如)是否关闭已打开的基础文件? 请参阅Files.list的javadoc的相关部分: 返回的流封装了DirectoryStream。如果需要及时处理文件系统资源,则应使用try-with- resources构造来确保在流操作完成之后调用流的close方法。 如果不调用,那么在生成可维护代码时最好的替代方法是什么? 问题答案: 终端操作员不会自动关闭流。考虑

  • 我正在将MySQL与Java结合使用,试图制作shoppingcartDB,并试图删除从订购到现在已经过了30天的元组。 但是编译器说: 我如何解决这个问题? 代码: 抛出异常的代码行是: stmt。executeUpdate(“从篮子中删除,其中orderdate=““Odate”;”);

  • 问题内容: 我只想知道,我们通常会在最后关闭流,但是为什么不通过以下方式关闭PrintStream 呢? 问题答案: 如果将其关闭,则将无法再写入控制台,因此,当进程终止时,让我们将此任务留给VM。您应该只关闭自己拥有或手动创建的流。不在您的控制范围之内,因此请留给创作者照顾。

  • 问题内容: 我被错误卡住了,这里的第42行是,请帮我解决这个问题,我在这个问题上待了几个小时。 这是我的代码: 问题答案: 一个对象只能有一个active对象,因此在执行时,第一个ResultSet()被关闭。 创建两个对象,一个用于,另一个用于。 引用以下内容的javadoc : 默认情况下,每个对象只能同时打开一个对象。因此,如果一个对象的读取与另一对象的读取交错,则每个对象必须已由不同的对象

  • 问题内容: 我被错误卡住了,这里的第42行是,请帮我解决这个问题,我在这里待了几个小时。 这是我的代码: 问题答案: 一个对象只能具有一个active对象,因此在执行时,第一个ResultSet()被关闭。 创建两个对象,一个用于,另一个用于。 引用以下内容的javadoc : 默认情况下,每个对象只能同时打开一个对象。因此,如果一个对象的读取与另一个对象的读取是交错的,则每个对象必须已由不同的对