FileReader が必ず close されるのかどうかの続き
FileReader が必ず close されるのかどうかの続き
FileReader が必ず close されるのかどうか ( http://nabetani.hatenablog.com/entry/2014/10/24/003239
)の続き。
結論
結論から書いてみる。
// 「BufferedReader に任せた」版 try (BufferedReader br = new BufferedReader(new FileReader(path))) { // do something. }
// 「FileReader close しすぎ」版 try ( FileReader fr = new FileReader(path); BufferedReader br = new BufferedReader(fr) ) { // do something. }
のどちらも正当。
私の場合
- 仕事で製品に入れるなら「FileReader close しすぎ」版を好む
- CodeIQ の解答とかに書くなら「BufferedReader に任せた」版を好む
と思う。
とはいえ、java.nio.file.Files.newBufferedReader が使えるのなら、そのほうが良い。
私について
実は。業務での Java 歴は1年ぐらいしかない。
CodeIQ で出す問題では、必要ならちゃんとコードを読む言語に入れているけど、正直あんまり自信がない。
状況をもう一度整理
「BufferedReader に任せた」版でマズイことが起こる条件は
A0. BufferedReader の new ( コンストラクタの前 ) でエラーが発生する
A1. BufferedReader のコンストラクタ内で例外・エラーが発生する
B. A で発生した例外・エラーがキャッチされ、処理が続く
C. リークしたハンドルが GC で回収されずに貯まる
という条件の組み合わせ( ( A0 or A1 ) and B and C ) が真になる場合に限られる。
順に見ていこう。
A0. BufferedReader の new ( コンストラクタの前 ) でエラーが発生する
これが発生するのはひどくまずい状況に限られる。
これが発生しない前提の仕事も多いと思う。
発生するのはメモリ不足だけなのか、クラスローダーとかが例外を投げることもあるのか、そのあたりはよくわかっていないんだけど、いずれにせよ、プロセスごと死んでもいい場合が多いと思う。
A1. BufferedReader のコンストラクタ内で例外・エラーが発生する
一方。
BufferedReader のコンストラクタ内には
new char[8192];
のようなことが書いてあり、状況によってはメモリ不足エラーは視野に入れておくべきだと思う。
※ 例外( Exception ) は発生しない。
結局どうなの?
これが原因で具体的にマズイことになることは極めて稀だと思う。
実際に発生する環境が用意できる気がしない。
稀とはいえ、私の理解が正しければ、「BufferedReader に任せた」版 だとトラブルになり、「FileReader close しすぎ」版 だとトラブルにならないという状況がありうる。
一方。「FileReader close しすぎ」版 は、正常系では FileReader を close しすぎていて、実行速度面でもメモリフットプリントでももったいない感じではある。
というわけで、どちらもメリット・デメリットがあるのでケースバイケースで使い分けるというのが正解だと思う。
で。
具体的には。
ウェブサーバー内で動くとか、組み込み機器内で動くとか言うことなら、「FileReader close しすぎ」版 がよい場合が多いと思う。
デスクトップアプリケーションなら、「FileReader close しすぎ」版 が良い場合が多いと思う。
ケースバイケースなんかめんどくさいからどっちかに決めたい、ということなら、「FileReader close しすぎ」版 が良いと思う。
「常にちょっと close しすぎ」と、「極稀にファイルハンドルリークするかも。しないかも。」だと、前者のほうがマシだと感じる。
とはいえ結局。
nio を使え、ということだと思う。
最後に
識者のツッコミお待ちしております。
追記
どうも、上記話は正しくなさそうな感じ。Java 難しい。
@Air_Hold nioの内部実装は
(略)
Reader reader = new InputStreamReader(newInputStream(path), decoder);
return new BufferedReader(reader);
— チョコレートバー (@Air_Hold) 2014, 10月 25
@Air_Hold
そこではtry-catchしてないですよ。
FileReaderのcloseが云々と言っておいて、newBufferedReader使えってのは意味不明すぎです。だからこそ太一さんは実装見ろとおっしゃったのですし。
— チョコレートバー (@Air_Hold) 2014, 10月 25