Java 7 のtry-with-resources構文 (ARM ブロック ( Automatic Resource Management ) とも呼ばれます) は、AutoCloseableリソースを 1 つだけ使用する場合に便利で、短くて簡単です。FileWriterただし、相互に依存する複数のリソースを宣言する必要がある場合、たとえば aと aBufferedWriterをラップする場合、どのイディオムが正しいかわかりません。もちろん、この質問は、AutoCloseableこれら 2 つの特定のクラスだけでなく、一部のリソースがラップされている場合にも関係します。
私は次の3つの選択肢を思いつきました:
1)
私が見た単純なイディオムは、ARM 管理の変数で最上位のラッパーのみを宣言することです。
static void printToFile1(String text, File file) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
これは素晴らしく短いですが、壊れています。基になるものは変数で宣言されていないため、生成されたブロックFileWriterで直接閉じられることはありません。ラッピングfinallyの 方法 で のみ 閉じます . 問題は、のコンストラクターから例外がスローされた場合、その例外が呼び出されないため、基になるものが閉じられないことです。closeBufferedWriterbwcloseFileWriter
2)
static void printToFile2(String text, File file) {
try (FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw)) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
ここでは、基になるリソースとラッピング リソースの両方が ARM 管理の変数で宣言されているため、どちらも確実に閉じられますが、基fw.close() になるリソースは 2 回呼び出されます。つまり、直接だけでなく、ラッピングを通じても呼び出されbw.close()ます。
CloseableのサブタイプであるAutoCloseable両方を実装するこれら 2 つの特定のクラスでは、これは問題にはなりませんclose。
このストリームを閉じて、それに関連付けられているシステム リソースを解放します。ストリームが既に閉じられている場合、このメソッドを呼び出しても効果はありません。
ただし、一般的なケースでは、 のみを実装するAutoCloseable(および実装しない) リソースを持つことができます。これは、複数回呼び出すことができることをCloseable保証しません。close
java.io.Closeable の close メソッドとは異なり、この close メソッドはべき等である必要がないことに注意してください。つまり、この close メソッドを複数回呼び出すと、目に見える副作用が生じる可能性があります。これは、複数回呼び出されても効果がないことが必要な Closeable.close とは異なります。ただし、このインターフェイスの実装者は、close メソッドを冪等にすることを強くお勧めします。
3)
static void printToFile3(String text, File file) {
try (FileWriter fw = new FileWriter(file)) {
BufferedWriter bw = new BufferedWriter(fw);
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
fwクリーンアップが必要な実際のリソースを表すのはのみであるため、このバージョンは理論的に正しいはずです。自体はbwリソースを保持せず、 に委譲するfwだけなので、基になる を閉じるだけで十分fwです。
一方、構文は少し不規則であり、Eclipse は警告を発行します。これは誤報だと思いますが、それでも対処しなければならない警告です。
リソース リーク: 'bw' は決して閉じられません
では、どのアプローチを採用すればよいでしょうか。それとも、正しいものである他のイディオムを見逃したことがありますか?