通常、最も外側のストリームを閉じるだけで問題ありません。これは、慣例により、基になるストリームでクローズをトリガーする必要があるためです。
したがって、通常、コードは次のようになります。
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
...
in.close(); // when you care about Exception-Handling in case when closing fails
}
finally {
IOUtils.closeQuietly(in); // ensure closing; Apache Commons IO
}
それにもかかわらず、ストリームが既に開かれている場合に、基になるストリーム コンストラクターが例外を発生させるというまれなケースがあるかもしれません。その場合、外側のコンストラクターが呼び出されず、in
null であるため、上記のコードは基になるストリームを閉じません。したがって、finally ブロックは何も閉じず、基になるストリームを開いたままにします。
Java 7以降、これを行うことができます:
try (OutputStream out1 = new ...; OutputStream out2 = new ...) {
...
out1.close(); //if you want Exceptions-Handling; otherwise skip this
out2.close(); //if you want Exceptions-Handling; otherwise skip this
} // out1 and out2 are auto-closed when leaving this block
ほとんどの場合、クローズ中に発生した場合の例外処理は必要ないため、これらの明示的な close() 呼び出しをスキップします。
編集
これは、このパターンを使用することが重要な非信者向けのコードです。closeQuietly()メソッドに関する Apache Commons IOUtils javadoc もお読みください。
OutputStream out1 = null;
OutputStream out2 = null;
try {
out1 = new ...;
out2 = new ...;
...
out1.close(); // can be skipped if we do not care about exception-handling while closing
out2.close(); // can be skipped if we ...
}
finally {
/*
* I've some custom methods in my projects overloading these
* closeQuietly() methods with a 2nd param taking a logger instance,
* because usually I do not want to react on Exceptions during close
* but want to see it in the logs when it happened.
*/
IOUtils.closeQuietly(out1);
IOUtils.closeQuietly(out2);
}
@Tom の「アドバイス」を使用すると、の作成で例外が発生out1
したときに開いたままになります。out2
このアドバイスは、It's a continual source of errors for obvious reasons.
まあ、私は盲目かもしれませんが、私には明らかではありません. トムのパターンはエラーが発生しやすいのに対し、私のパターンは考えられるすべてのユースケースで馬鹿げた安全です。