Yabu.log

ITなどの雑記

Effective Java Item 9: Prefer try-with-resources to try-finally

try-finallyよりtry-with-resourcesを使え

Effective Java (3rd Edition)

Effective Java (3rd Edition)

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回連続で重ねるのって英語的に正しいのか? 強調表現みたいな意味になるのだろうか。

*1:Java Puzzleの41。長年誰も気付かなかった