当前位置:  开发笔记 > 编程语言 > 正文

为什么Files.lines(和类似的Streams)不会自动关闭?

如何解决《为什么Files.lines(和类似的Streams)不会自动关闭?》经验,为你挑选了2个好方法。

Stream的javadoc说明:

Streams有一个BaseStream.close()方法并实现AutoCloseable,但几乎所有的流实例实际上都不需要在使用后关闭.通常,只有源为IO通道的流(例如Files.lines(Path,Charset)返回的流)才需要关闭.大多数流都由集合,数组或生成函数支持,不需要特殊的资源管理.(如果流确实需要关闭,则可以在try-with-resources语句中将其声明为资源.)

因此,绝大多数情况下,人们可以在单行中使用Streams,collection.stream().forEach(System.out::println);但是对于Files.lines和其他资源支持的流,必须使用try-with-resources语句或泄漏资源.

这让我觉得容易出错并且不必要.因为Streams只能迭代一次,所以在我看来,没有一个迭代后Files.lines不应该关闭输出的情况,因此实现应该只是在任何终端操作结束时隐式调用close .我错了吗?



1> Brian Goetz..:

是的,这是一个深思熟虑的决定.我们考虑了两种选择.

这里的操作设计原则是"获取资源的人应该释放资源".阅读EOF时文件不会自动关闭; 我们希望打开文件的人明确关闭文件.由IO资源支持的流是相同的.

幸运的是,该语言为您提供了一种自动化的机制:try-with-resources.由于Stream实现AutoCloseable,您可以执行以下操作:

try (Stream s = Files.lines(...)) {
    s.forEach(...);
}

"自动关闭真的很方便,所以我可以把它写成一个单行"的说法很好,但主要是尾巴摇尾巴.如果您打开了文件或其他资源,则还应该准备关闭它.有效和一致的资源管理胜过"我想在一行中写出来",我们选择不扭曲设计只是为了保持一线性.


在我看来,这很难注意到.它不在Files.lines()javadoc中,如果您将终止操作放在同一行并且没有Stream作为变量,则Eclipse不会警告资源未被关闭.

2> Tagir Valeev..:

除了@BrianGoetz之外,我还有更具体的例子.不要忘记Stream有逃生舱的方法iterator().假设你这样做:

Iterator iterator = Files.lines(path).iterator();

之后,你可以调用hasNext()next()几次,然后就放弃这个迭代器Iterator接口完美支持这样使用.没有办法明确关闭Iterator,你可以在这里关闭的唯一对象是Stream.所以这样它可以很好地工作:

try(Stream stream = Files.lines(path)) {
    Iterator iterator = stream.iterator();
    // use iterator in any way you want and abandon it at any moment
} // file is correctly closed here.

推荐阅读
U友50081205_653
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有