Agu*_*uid 3 java java-8 java-stream
在Java 8中,Stream(AutoCloseable)无法重用,一旦消耗或使用它,流将被关闭.那么使用try-with-resources语句声明的实用程序是什么?
使用try-with-resources语句的示例:
public static void main(String[] args) throws IOException {
try (Stream<Path> entries
= Files.walk(Paths.get("."), 4, FileVisitOption.FOLLOW_LINKS)) {
entries.forEach(x -> System.out.println(x.toAbsolutePath()));// the entries stream will be automatically closed at this point
//..
System.out.println("Still in the Try Block");
} //The entries will be closed again because it is declared in the try-with-resources statement
}
Run Code Online (Sandbox Code Playgroud)
这里是没有try catch块的相同示例
public static void main(String[] args) throws IOException {
Stream<Path> entries = Files.walk(Paths.get("."), 4, FileVisitOption.FOLLOW_LINKS);
entries.forEach(x -> System.out.println(x.toAbsolutePath()));// the entries stream will be automatically closed at this point
System.out.println("Is there a risk of resources leak ?");
}
Run Code Online (Sandbox Code Playgroud)
哪一个更安全?
在一些答案后,我更新我的代码以检查流是否已关闭:
这里有新代码:
public static void main(String[] args) throws IOException {
resourceWithTry();
resourceWithoutTry();
}
private static void resourceWithTry() throws IOException {
try (Stream<Path> entries
= Files.walk(Paths.get("."), 4, FileVisitOption.FOLLOW_LINKS).onClose(() -> System.out.println("The Stream is closed"))) {
entries.forEach(x -> System.out.println(x.toAbsolutePath()));// the entries stream will be not automatically closed at this point
System.out.println("Still in the Try Block");
} //The entries will be closed again because it is declared in the try-with-resources statement
}
private static void resourceWithoutTry() throws IOException {
Stream<Path> entries
= Files.walk(Paths.get("."), 4, FileVisitOption.FOLLOW_LINKS).onClose(() -> System.out.println("Without Try: The Stream is closed"));
entries.forEach(x -> System.out.println(x.toAbsolutePath()));// the entries stream will be not automatically closed at this point
System.out.println("Still in the Try Block");
}
Run Code Online (Sandbox Code Playgroud)
在Java 8中,Stream(AutoCloseable)无法重用,一旦消耗或使用它,流将被关闭.
不完全是.
Stream
终端操作如forEach()
不关闭流.
它使流管道不再消耗.
哪个是不同的.
在执行终端操作之后,流管道被认为已消耗,并且不能再使用; 如果需要再次遍历同一数据源,则必须返回数据源以获取新流.
它没有说流已关闭.
因此,在以下代码中,永远不会调用实例的AutoCloseable.close()
方法Stream
:
Stream<Path> entries = Files.walk(Paths.get("."), 4, FileVisitOption.FOLLOW_LINKS);
entries.forEach(x -> System.out.println(x.toAbsolutePath()));
Run Code Online (Sandbox Code Playgroud)
那么它总是需要关闭流吗?(使用显式close()
调用或更好try-with-resources
)
java.util.stream.Stream<T>
javadocs解释说,几乎所有Stream
实例都不需要AutoCloseable.close()
在使用后关闭.
这只适用于IO流.
Streams有一个close()方法并实现AutoCloseable,但几乎所有流实例实际上都不需要在使用后关闭.通常,只有源为IO通道的流(例如Files.lines(Path,Charset)返回的流)才需要关闭.大多数流都由集合,数组或生成函数支持,不需要特殊的资源管理.(如果流确实需要关闭,则可以在try-with-resources语句中将其声明为资源.)
在我们的例子中,你操纵File
s,所以关闭频道是有意义的.
通过使用a try-with-resources
,可以避免可能发生的资源耗尽异常和错误.
如果在处理过程中出现任何错误或异常,则资源可能会全部释放.
流处理可能会被中断,然后它不会被完全消耗,也不会自动关闭。考虑这个例子:
Stream<Integer> nums = Stream.of(1, 2, 3);
nums.onClose(() -> System.out.println("close was called"));
nums.forEach(x -> { if (x > 1) throw new IllegalStateException(); });
Run Code Online (Sandbox Code Playgroud)
这会在中间崩溃,并且onClose
不会被调用。该流保持打开状态,您必须手动将其关闭。
如果您使用try-with-resources ,无论如何它都会正确关闭,正如您所观察到的:
try (Stream<Integer> nums = Stream.of(1, 2, 3)) {
nums.onClose(() -> System.out.println("close was called"));
nums.forEach(x -> { if (x > 1) throw new IllegalStateException(); });
}
Run Code Online (Sandbox Code Playgroud)
这是一个令人痛苦的示例,因为它不消耗任何需要关闭的资源,所以即使流未关闭,垃圾收集器也会进行清理。
那么用 try-with-resources 语句声明的实用程序是什么?
它确保无论如何都会关闭流。当流不受需要关闭的资源支持时,实际上并不重要。
上面的例子只是为了演示差异,但在这样的代码中,使用 try-with-resources 是不必要的偏执,只是代码中的噪音,所以不使用 try-with-resources 实际上会更好。
归档时间: |
|
查看次数: |
787 次 |
最近记录: |