1 回答

TA貢獻1788條經驗 獲得超4個贊
有一些方法。
使用“圍繞執行”成語。重新制定接口以簡化客戶端實現并消除問題。
忽略問題。聽起來很愚蠢,但這通常是使用 I/O 流裝飾器包裝時發生的情況。
包裝在代理中,并將其放在試用資源中。
AutoCloseable
寫出與資源一起嘗試使用嘗試捕獲和嘗試最終的等效項。(我不會 - 討厭。
將修改后的試用資源編寫為庫功能。此代碼將成為執行周圍的客戶端。
編寫異常處理舊學校風格與嘗試捕捉和嘗試最終。
編輯:我想我會重新審視答案,添加一些示例代碼來娛樂。
圍繞成語執行
簡單而最好的解決方案。不幸的是,Java庫并不經常使用它(這是一個很大的例外),并且約定也沒有很好地建立。與以往一樣,Java在沒有支持功能的情況下檢查的異常使事情變得棘手。我們不能使用,必須發明我們自己的功能接口。AccessController.doPrivileged
java.util.function
// Like Consumer, but with an exception.
interface Use<R, EXC extends Exception> {
void use(R resource) throws EXC;
}
public static void withThing(String name, Use<InputStream,IOException> use) throws IOException {
try (InputStream in = new FileInputStream(name)) {
use.use(in);
}
}
很好,很簡單。無需擔心客戶端代碼會弄亂資源處理,因為它不會這樣做。好。
修改后的“使用資源試用”作為庫功能,作為代理實現,可在“使用資源試用”中自動關閉
它會變得丑陋。我們需要將獲取、發布和初始化作為 lambdas 傳遞。直接在此方法中創建資源將打開一個小窗口,其中意外的異常會導致泄漏。
public static InputStream newThing(String name) throws IOException {
return returnResource(
() -> new FileInputStream(name),
InputStream::close,
in -> {
int ignore = in.read(); // some work
}
);
}
的一般實現將類似于下面的這個黑客。這是一個黑客,因為嘗試資源不支持這種事情,Java庫不支持檢查異常。請注意,限制為一個例外(對于未選中的例外,可以使用未選中的例外)。returnResource
interface Acquire<R, EXC extends Exception> {
R acquire() throws EXC;
}
// Effectively the same as Use, but different.
interface Release<R, EXC extends Exception> {
void release(R resource) throws EXC;
}
public static <R, EXC extends Exception> R returnResource(
Acquire<R, EXC> acquire, Release<R, EXC> release, Use<R, EXC> initialize
) throws EXC {
try (var adapter = new AutoCloseable() { // anonymous classes still define type
private R resource = acquire.acquire();
R get() {
return resource;
}
void success() {
resource = null;;
}
public void close() throws EXC {
if (resource != null) {
release.release(resource);
}
}
}) {
R resource = adapter.get();
initialize.use(resource);
adapter.success();
return resource;
}
}
如果我們將構建資源的參數與資源的構造分開,這可能會更干凈。
public static InputStream newThing(String name) throws IOException {
return returnResource(
name,
FileInputStream::new,
InputStream::close,
in -> {
int ignore = in.read(); // some work
}
);
}
// Like Function, but with a more descriptive name for a functional interface.
interface AcquireFrom<T, R, EXC extends Exception> {
R acquire(T t) throws EXC;
}
public static <T, R, EXC extends Exception> R returnResource(
T t, AcquireFrom<T, R, EXC> acquire, Release<R, EXC> release, Use<R, EXC> initialize
) throws EXC {
return returnResource(() -> acquire.acquire(t), release, initialize);
}
因此,總而言之,以下事情是痛苦的:
轉讓資源所有權。將其保留在本地。
java.util.function
不支持選中的異常。Java 庫不支持執行周圍。
AutoCloseable::close
聲明它拋出而不是成為類型的類型參數。Exception
已檢查沒有總和類型的異常。
一般的 Java 語言語法。
添加回答
舉報