2016-12-07 74 views
4

Autocloseable應始終與try-with-resources一起使用。至少Intellij檢查表明它。 所以,如果我有一個產生Foo實現Autocloseable我應該做的代碼:Java8中的「Autocloseable」的數組或集合

try (final Foo foo = getFoo()) { 
    foo.doSomething(); 
} 

但如果我有函數,返回Foo[]?或接受Foo[](或Collection<Foo>)作爲參數的函數?如何使用try-with-resources? 着眼於以下功能:

Foo[] getFoos(); 
doAll(Foo... foo); 

我想要做的事行doAll(getFoos())

我怎麼能這樣做?

回答

4

Try-with-resources語句只能關閉在頭文件中聲明並分配的資源。所以唯一的方法是讓你正在收集的Collection實現AutoCloseable或者將它包裝到你的AutoCloseable擴展中,所以它的close()方法將被T-W-R調用。像:

try (SomeAutoCloseableCollction col = getAutoCloseables()) { 
     System.out.println("work"); 
} //col.close() gets called 

對於一個數組,恐怕沒有辦法,因爲你不能擴展它並使它實現一些接口。


如果你自己收集,可看Apache Drill項目和org.apache.drill.common.AutoCloseables類 - 它正是這麼做的,其本身關閉大量AutoCloseables的。

1

正如其他答案指出,這是不可能的。但是,您應該問自己爲什麼需要將整個集合放入AutoCloseable中。如果你想確保每個元素都被處理後關閉,你可以這樣做:

Foo[] foos = getFoos(); 
for (int i = 0; i < foos.length; i++) { 
    try (Foo foo = foos[i]) { 
    // Your code here 
    } 
} 
+0

我無法找到一種方法,使與增強的for循環這項工作,但如果真有人看到的方式,請更新我的編輯答案。 –

+4

你的意思是for(Foo foo:getFoos())try(Foo toClose = foo){/ * code * /}'?這應該工作。 – Holger

3

您可以創建AutoCloseable小號合併到一個單一的一個方法,將安全地關閉所有的人:

public static AutoCloseable closeBoth(AutoCloseable a, AutoCloseable b) { 
    if(a==null) return b; 
    if(b==null) return a; 
    return() -> { try(AutoCloseable first=a) { b.close(); } }; 
} 
public static AutoCloseable closeAll(AutoCloseable... c) { 
    return Arrays.stream(c).reduce(null, MyClass::closeBoth); 
} 

它們允許使用數組返回方法類似

Foo[] foo; 
try(AutoCloseable closeAll = MyClass.closeAll(foo=getFoos())) { 
    /* 
     use foo 
    */ 
}