fan*_*fan 21 java eclipse java-8 java-stream
我认为流API在这里使代码更容易阅读.我发现了一些很烦人的东西.的Stream接口(java.util.stream.Stream)延伸的AutoClosable接口(java.lang.AutoCloseable)
因此,如果要正确关闭流,则必须使用try with resources.
清单1.不太好,溪流没有关闭.
public void noTryWithResource() {
Set<Integer> photos = new HashSet<Integer>(Arrays.asList(1, 2, 3));
@SuppressWarnings("resource") List<ImageView> collect = photos.stream()
.map(photo -> new ImageView(new Image(String.valueOf(photo)))).collect(Collectors.<ImageView>toList());
}
Run Code Online (Sandbox Code Playgroud)
清单2.2个imbricated尝试:(
public void tryWithResource() {
Set<Integer> photos = new HashSet<Integer>(Arrays.asList(1, 2, 3));
try (Stream<Integer> stream = photos.stream()) {
try (Stream<ImageView> map = stream
.map(photo -> new ImageView(new Image(String.valueOf(photo))))) {
List<ImageView> collect = map.collect(Collectors.<ImageView>toList());
}
}
}
Run Code Online (Sandbox Code Playgroud)
清单3.当map返回流时,必须关闭stream()和map()函数.
public void tryWithResource2() {
Set<Integer> photos = new HashSet<Integer>(Arrays.asList(1, 2, 3));
try (Stream<Integer> stream = photos.stream();
Stream<ImageView> map = stream
.map(photo -> new ImageView(new Image(String.valueOf(photo))))) {
List<ImageView> collect = map.collect(Collectors.<ImageView>toList());
}
}
Run Code Online (Sandbox Code Playgroud)
我给出的例子没有任何意义.为了这个例子,我用Pathjpg图像替换Integer了.但是不要让你分心这些细节.
使用那些可自动关闭的流的最佳方法是什么.我不得不说我对我展示的3个选项中的任何一个都不满意.你怎么看?还有其他更优雅的解决方案吗?
Stu*_*rks 27
你正在使用@SuppressWarnings("resource")哪个可能会抑制关于未封闭资源的警告.这不是发出的警告之一javac.Web搜索似乎表明,如果AutoCloseable未关闭,Eclipse会发出警告.
根据引入的Java 7规范,这是一个合理的警告AutoCloseable:
在不再需要时必须关闭的资源.
然而,Java的8规格的AutoCloseable很轻松删除"必须关闭"的条款.它现在部分地说
一个可以保存资源的对象......直到它被关闭.
对于基类来说,实现AutoCloseable是可能的,并且实际上是常见的,即使并非所有子类或实例都将保留可释放的资源.对于必须完全通用运行的代码,或者当已知AutoCloseable实例需要资源释放时,建议使用try-with-resources结构.但是,当使用支持基于I/O和非I/O的表单的Stream等工具时,在使用非基于I/O的表单时,通常不需要try-with-resources块.
Lambda专家组对此问题进行了广泛讨论; 此消息总结了该决定.除其他事项外,它提到了AutoCloseable规范(上面引用)和BaseStream规范(其他答案引用)的变化.它还提到可能需要针对更改的语义调整Eclipse代码检查器,可能不会无条件地发出AutoCloseable对象的警告.显然这条消息没有传达给Eclipse的人,或者他们还没有改变它.
总之,如果Eclipse警告引导您认为您需要关闭所有AutoCloseable对象,那就不正确了.只AutoCloseable需要关闭某些特定对象.Eclipse需要修复(如果还没有)不要为所有AutoCloseable对象发出警告.
dka*_*zel 12
如果流需要对其自身进行任何清理(通常是I/O),则只需关闭Streams.您的示例使用HashSet,因此不需要关闭它.
来自Stream javadoc:
通常,只有源为IO通道的流(例如Files.lines(Path,Charset)返回的流)才需要关闭.大多数流都由集合,数组或生成函数支持,不需要特殊的资源管理.
所以在你的例子中,这应该没有问题
List<ImageView> collect = photos.stream()
.map(photo -> ...)
.collect(toList());
Run Code Online (Sandbox Code Playgroud)
编辑
即使您需要清理资源,您也应该只使用一次try-with-resource.让我们假装您正在读取一个文件,其中文件中的每一行都是图像的路径:
try(Stream<String> lines = Files.lines(file)){
List<ImageView> collect = lines
.map(line -> new ImageView( ImageIO.read(new File(line)))
.collect(toList());
}
Run Code Online (Sandbox Code Playgroud)
"可关闭"表示"可以关闭",而不是"必须关闭".
这在过去是正确的,例如见ByteArrayOutputStream:
关闭a
ByteArrayOutputStream没有效果.
而且,现在是真正的为StreamS其中的文件明确:
Streams有一个
BaseStream.close()方法和实现AutoCloseable,但几乎所有的流实例实际上都不需要在使用后关闭.通常,只有源为IO通道的流(例如返回的流Files.lines(Path, Charset))才需要关闭.
因此,如果审计工具生成错误警告,则是审计工具的问题,而不是API的问题.
请注意,即使您要添加资源管理,也不需要嵌套try语句.虽然以下就足够了:
final Path p = Paths.get(System.getProperty("java.home"), "COPYRIGHT");
try(Stream<String> stream=Files.lines(p, StandardCharsets.ISO_8859_1)) {
System.out.println(stream.filter(s->s.contains("Oracle")).count());
}
Run Code Online (Sandbox Code Playgroud)
您也可以将辅助Stream资源添加到资源管理中,而无需额外的try:
final Path p = Paths.get(System.getProperty("java.home"), "COPYRIGHT");
try(Stream<String> stream=Files.lines(p, StandardCharsets.ISO_8859_1);
Stream<String> filtered=stream.filter(s->s.contains("Oracle"))) {
System.out.println(filtered.count());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18967 次 |
| 最近记录: |