假设我有3个扫描程序实例,我想关闭它。
我能做到
sc.close()
为每个扫描仪。
或者我可以做类似
的事情for (Scanner sc: new Scanner[]{sc1,sc2,sc3}) {
sc.close();
}
使用Java 8有没有更短的方法?
类似于什么?
{sc1,sc2,sc3}.forEach((sc) -> sc.close());
答案 0 :(得分:73)
从Java 7开始,您应该使用try-with-resources
try(Scanner sc1 = new Scanner("");
Scanner sc2 = new Scanner("");
Scanner sc3 = new Scanner("")){
}
//all scanners get closed implicitly
所以你根本不需要任何代码。
所有for-each或stream构造的问题是,理论上 - 如果第一个close()
在调用基础源close()
方法时出现异常,则以下扫描程序不会被关闭。 Scanner.close()
实现捕获任何IOException,但不会发生其他异常。
try-with-resources构造处理的是,循环不是。
编辑:虽然您的问题针对更一般的方法,但上述解决方案是对您的特定问题的回应:处理AutoCloseable
资源,无论如何都应该使用使用 try-with-resources 构造,根本不需要对close方法进行特殊处理(=对特定问题的最短解决方案)。
关于处理任意项目(没有资源)的更一般的问题,Java至少有两个选择:
从Array / Varargs创建一个列表并迭代它
for(YourItemType item : Arrays.asList(your,items,here)) {
//do something
}
从Array / Varargs创建流并向其应用函数
Stream.of(your,items,here).forEach(item -> { doSomething});
当然" doSomething"可以用方法参考替换
Stream.of(your,items,here).forEach(this::myMethod);
...
void myMethod(YourItemType item){
//doSomething
}
该方法的问题是,必须在lambda表达式中显式处理已检查的异常。让我们看一下上面的例子,让myMethod
抛出一个检查过的异常
void myMethod(YourItemType item) throws Exception
在这种情况下,您的stream语句必须看起来像
Stream.of(your,items,here).forEach(item -> {
try {
myMethod(item);
} catch (Exception e){
//omit or throw new RuntimeException(e);
};
这看起来并不好看。但我们可以将lambda体放在一个单独的方法中
void myMethodQuietly(YourItemType item) {
try {
myMethod(item);
}catch(Exception e){
//omit or throw new RuntimeException(e);
}
}
Stream.of(your,items,here).forEach(this::myMethodQuietly);
这种方法可能对您的特定资源问题感兴趣。我们可以将所有这些放入CompositeAutoCloseable
中,该close()
将在类外部创建的资源在调用public class CompositeAutoCloseable implements AutoCloseable {
private List<Closeable> resources;
public CompositeAutoCloseable(Closeable... resources) {
this.resources = Arrays.asList(resources);
//you could use a stream here too
}
@Override
public void close() {
this.resources.stream().forEach(this::closeQuietly);
}
void closeQuietly(Closeable res) {
if(res == null) {
return;
}
try {
res.close();
}catch(Exception e){
//omit
}
}
}
时安全地关闭所有资源
try(CompositeAutoCloseable cac = new CompositeAutoCloseable(sc1,sc2,sc3)) {
//do something
}
一旦你有了这样的助手类,你可以再次使用try-with-resources。
{{1}}
我让你知道与初始解决方案相比这是否合理;)
答案 1 :(得分:3)
如果将实例化与处置分开,请使用Guava的com.google.common.io.Closer。
答案 2 :(得分:-1)
尽管代码长度与其质量之间有时存在相关性,但这并不是用于选择代码的良好标准。
我可能会使用varargs并执行以下操作:
print()