假设我有3个扫描程序实例,我想关闭它.
我可以
sc.close()
Run Code Online (Sandbox Code Playgroud)
对于每个扫描仪.
或者我可以做类似的事情
for (Scanner sc: new Scanner[]{sc1,sc2,sc3}) {
sc.close();
}
Run Code Online (Sandbox Code Playgroud)
使用Java 8有没有更短的方法?
类似的东西?
{sc1,sc2,sc3}.forEach((sc) -> sc.close());
Run Code Online (Sandbox Code Playgroud)
Ger*_*cke 73
从Java 7开始,您应该使用try-with-resources
try(Scanner sc1 = new Scanner("");
Scanner sc2 = new Scanner("");
Scanner sc3 = new Scanner("")){
}
//all scanners get closed implicitly
Run Code Online (Sandbox Code Playgroud)
所以你根本不需要任何代码.
所有for-each或流构造的问题在于 - 理论上 - 如果第close()一个在调用底层源close()方法时出现异常失败,则以下扫描程序将不会关闭.该Scanner.close()实现捕获任何IOException,但不会发生其他异常.
try-with-resources构造处理它,循环不处理.
编辑:虽然你的问题针对更一般的方法,但上述解决方案是对你的特定问题的回应:处理AutoCloseable资源,在任何情况下都应该与资源试用结构一起使用,不需要特殊处理完全关闭方法(=对您的特定问题的最短解决方案).
关于处理任意项(不是资源)的更普遍的问题,Java至少有两个选择:
从Array/Varargs创建一个List并迭代它
for(YourItemType item : Arrays.asList(your,items,here)) {
//do something
}
Run Code Online (Sandbox Code Playgroud)
从Array/Varargs创建流并将函数应用于它
Stream.of(your,items,here).forEach(item -> { doSomething});
Run Code Online (Sandbox Code Playgroud)
当然,"doSomething"可以用方法参考替换
Stream.of(your,items,here).forEach(this::myMethod);
...
void myMethod(YourItemType item){
//doSomething
}
Run Code Online (Sandbox Code Playgroud)
该方法的问题是,必须在lambda表达式中显式处理已检查的异常.让我们拿上面的例子,myMethod抛出一个检查过的异常
void myMethod(YourItemType item) throws Exception
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您的流语句必须看起来像
Stream.of(your,items,here).forEach(item -> {
try {
myMethod(item);
} catch (Exception e){
//omit or throw new RuntimeException(e);
};
Run Code Online (Sandbox Code Playgroud)
这看起来不太好.但我们可以将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);
Run Code Online (Sandbox Code Playgroud)
您的特定资源问题可能会对此方法感兴趣.我们可以将所有这些放入一个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
}
}
}
Run Code Online (Sandbox Code Playgroud)
一旦你有这样一个帮助类,你可以再次使用try-with-resources.
try(CompositeAutoCloseable cac = new CompositeAutoCloseable(sc1,sc2,sc3)) {
//do something
}
Run Code Online (Sandbox Code Playgroud)
我把它留给你来决定与初始解决方案相比这是否合理;)