PGBox
P
G
Box

try後の自動的なclose呼び出し

Java7のメニューへ戻る



使用した環境
JDK 7 Update 4

finallyを使って行っていたclose処理を自動化する事が可能です


Java6まではファイルの読み込みやDB接続など、処理の終了時に必ずclose()の呼び出しが必要となる場面では
try ~ finally といったように、tryステートメントで処理全体を囲んだ上で
finally内でclose()を呼び出すようなソースを書く必要がありました。

(Java6までの記述方法)
        
BufferedReader br = null;
try {
    br = new BufferedReader(new FileReader("d:/work/aaa.txt"));
    
    System.out.println(br.readLine());
    
} finally {
    if (br != null) {
        br.close();
    }
}


Java7からは、下記のように簡略化できるようになりました。
try (BufferedReader br = new BufferedReader(new FileReader("d:/work/aaa.txt"))) {
    
    System.out.println(br.readLine());
    
}



セミコロンで区切る事によって、複数の変数をclose()対象にする事もできます。
try (BufferedReader br = new BufferedReader(new FileReader("d:/work/aaa.txt")); 
        BufferedReader br2 = new BufferedReader(new FileReader("d:/work/bbb.txt"))) {
    
    System.out.println(br.readLine());
    System.out.println(br2.readLine());
    
}



tryステートメント内での自動クローズですが、java.lang.AutoClosableインターフェイスを実装している
クラスであれば利用する事ができます。

また、AutoClosable#closeは、finallyの直前に呼び出されます。

public class Test {
    
    
    public static void main(String[] args) throws Exception {
        
        System.out.println("begin");
        
        try (CloseTest test = new CloseTest()) {
            System.out.println("process...");
            
        } finally {
            System.out.println("finally");
            
        }
        
        System.out.println("end");
        
    }
    

}

class CloseTest implements AutoCloseable {

    @Override
    public void close() throws IOException {
        System.out.println("close()");
        
    }
    
    
}


実行結果は下記のようになります。
finally処理の直前にclose()メソッドがコールされている事が分かります。

begin
process...
close()
finally
end




AutoCloseable#closeメソッド内でExceptionが発生した場合はそのままthrowされます。
この動作を検証するサンプルは下記の通りです。
 1: import java.io.IOException;
 2: 
 3: 
 4: public class Test {
 5: 
 6:    
 7:    public static void main(String[] args) throws Exception {
 8:        
 9:        System.out.println("begin");
10:        
11:        try (CloseTest test = new CloseTest()) {
12:            System.out.println("process...");
13:            
14:        } finally {
15:            System.out.println("finally");
16:            
17:        }
18:        
19:        System.out.println("end");
20:        
21:    }
22: 
23: }
24: 
25: class CloseTest implements AutoCloseable {
26: 
27:     @Override
28:     public void close() throws IOException {
29:         throw new IOException("test of Exception");
30:         
31:     }
32:     
33:     
34: }


実行結果は下記のようになります。
begin
process...
finally
Exception in thread "main" java.io.IOException: test of Exception
    at CloseTest.close(Test.java:30)
    at Test.main(Test.java:14)



スタックトレースを見てみると、Test.java:14となっており、finallyの直前でExceptionが投げられた扱いになっている事が分かります。
また、AutoCloseable#close内でExceptionが投げられた場合であっても、親ルーチン内のfinallyが呼び出されている事が分かります。





Java7のメニューへ戻る