Java 7のtry-with-resources構文(ARMブロック(自動リソース管理)とも呼ばれます)は、AutoCloseableリソースを1つだけ使用する場合に便利で短く、簡単です。ただし、相互に依存する複数のリソースを宣言する必要がある場合、たとえばa FileWriterとa BufferedWriterをラップすることで、正しいイディオムが何であるかわかりません。もちろん、この質問は、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ブロックで直接閉じられることはありません。closeラッピングの方法でのみ閉じられBufferedWriterます。問題は、bwのコンストラクタから例外がスローされた場合、その例外がclose呼び出されないため、基にFileWriter なるものが閉じられないことです。
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()ます。
これは、両方が実装するこれらの2つの特定のクラスCloseable(のサブタイプAutoCloseable)の問題にはなりませんclose。
このストリームを閉じ、それに関連付けられているすべてのシステムリソースを解放します。ストリームがすでに閉じている場合、このメソッドを呼び出しても効果はありません。
しかし、一般的なケースでは、私が唯一の実装リソース持つことができますAutoCloseable(とされていないCloseableことを保証するものではない)、close複数回呼び出すことができます。
java.io.Closeableのcloseメソッドとは異なり、このcloseメソッドはべき等である必要はないことに注意してください。つまり、このcloseメソッドを2回以上呼び出すと、目に見える副作用が発生する可能性があります。これは、2回以上呼び出すと効果がないことが必要な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'は決して閉じられません
それでは、どのアプローチを採用するのでしょうか。または、正しい他のイディオムを逃したことがありますか?
public BufferedWriter(Writer out, int sz)をスローすることができIllegalArgumentExceptionます。また、BufferedWriterを拡張して、コンストラクターから何かをスローするクラスや、必要なカスタムラッパーを作成するクラスを追加することもできます。
BufferedWriterコンストラクタが簡単に例外をスローすることができます。OutOfMemoryErrorバッファにかなりの量のメモリを割り当てるため、おそらく最も一般的なものです(ただし、プロセス全体を再起動する必要があることを示す場合があります)。/あなたはする必要がありflush、あなたのBufferedWriterお近くにないと内容(一般的に維持したい場合のみ、非例外ケースを)。FileWriter「デフォルト」のファイルエンコーディングを取得します。明示的にすることをお勧めします。