Effective Java Item 9: Prefer try-with-resources to try-finally
try-finallyよりtry-with-resourcesを使え
- 作者: Joshua Bloch
- 出版社/メーカー: Addison-Wesley Professional
- 発売日: 2018/01/06
- メディア: ペーパーバック
- この商品を含むブログ (2件) を見る
finallyの実装は難しい。著者の別の本やJDKにもfinallyがらみのミスが見つかっている*1
以下はJavaPuzzleに書かれている誤まった実装
} finally { if (in != null) { try { in.close(); } catch (IOException ex) { // There is nothing we can do if close fails } } if (out != null) { try { out.close(); } catch (IOException ex) { // Again, there is nothing we can do if close fails } } }
何が違うのかよくわからなかったが、StackOverFlowにドンピシャな質問があった。 try catch - What is wrong with this Java Puzzlers piece of code? - Stack Overflow
どうやら1つ目のclose時にcatchブロックで扱えない例外が発生した際に、2つ目の資源のcloseが漏れてしまうようだ。
複数リソースがある時のtry-finallyの正しい実装が以下のようになる
static void copy(String src,String dst)throws IOException{ InputStream in = new FileInputStream(src); try { OutputStream out = new FileOutputStream(dst); try { byte[] buf = new byte[BUFFER_SIZE]; int n; while ((n = in.read(buf)) >=0) out.write(buf,0,n); }finally { out.close(); } }finally { in.close(); }
try-with-resource
AutoCloseableを実装したクラスで可能。 AutoCloseable (Java SE 9 & JDK 9 )
tryの丸括弧の中に利用したいインスタンスを書くことでAutoCloseable.close()が漏れずに実施される。
try(InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst)){ byte[] buf = new byte[BUFFER_SIZE]; int n; while((n = in.read(buf))>=0) out.write(buf,0,n); }
余談
try-with-resources - the the best way to close resources
なんて一文があるけど、theを2回連続で重ねるのって英語的に正しいのか? 強調表現みたいな意味になるのだろうか。