流上的终端操作是否关闭源?

请考虑以下代码:

Path directory = Paths.get(/* some directory */); Files.list(directory).forEach(System.out::println); 

终端操作(如forEach )是否关闭已打开的基础文件?

请参阅Files.list的javadoc的相关部分:

返回的流封装了DirectoryStream。 如果需要及时处理文件系统资源,则应使用try-with-resources构造来确保在流操作完成后调用流的close方法。

如果它不调用Stream.close() ,那么在生成可维护代码时调用它的最佳选择是什么?

终端运营商不会自动关闭流。 考虑以下代码:

 Stream list = Files.list(directory).onClose(() -> System.out.println("Closed")); list.forEach(System.out::println); 

这不会打印“已关闭”。

但是,以下打印“已关闭”:

 try (Stream list = Files.list(directory).onClose(() -> System.out.println("Closed"))) { list.forEach(System.out::println); } 

因此,最好的方法是使用try-with-resources机制。

因此,快速检查显示forEach不会关闭DirectoryStream

 import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.function.Consumer; import java.util.stream.Stream; /** * Created for http://stackoverflow.com/q/27381329/1266906 */ public class FileList { public static void main(String[] args) { Path directory = Paths.get("C:\\"); try { Stream list = Files.list(directory).onClose(() -> System.out.println("Close called")); list.forEach(System.out::println); // Next Line throws "java.lang.IllegalStateException: stream has already been operated upon or closed" even though "Close called" was not printed list.forEach(System.out::println); } catch (IOException | IllegalStateException e) { e.printStackTrace(); // TODO: implement catch } // The mentioned try-with-resources construct try (Stream list = Files.list(directory)) { list.forEach(System.out::println); } catch (IOException | IllegalStateException e) { e.printStackTrace(); // TODO: implement catch } // Own helper-method try { forEachThenClose(Files.list(directory), System.out::println); } catch (IOException | IllegalStateException e) { e.printStackTrace(); // TODO: implement catch } } public static  void forEachThenClose(Stream list, Consumer action) { try { list.forEach(action); } finally { list.close(); } } } 

我看到两个缓解措施:

  1. 使用Files.list JavaDoc中所述的try-with-resources
  2. 编写自己的helper-method,它使用finally块

哪个更易于维护可能取决于您需要多少辅助方法。