try-with-resourcesは大体IOExceptionが発生するものに対してのみ使えると思っていましたが、。
AutoCloseableで様々なクラスに対して有効化できるらしい。
#try-with-resourcesについて
try-with-resourcesステートメントは、1つ以上のリソースを宣言するtryステートメントです。 リソースは、プログラムが終了した後に閉じる必要があるオブジェクトです。 try-with-resourcesステートメントは、各リソースがステートメントの最後で確実に閉じられるようにします。 java.io.Closeableを実装するすべてのオブジェクトを含む、java.lang.AutoCloseableを実装するすべてのオブジェクトをリソースとして使用できます。
Oracle Java Documentation
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
つまり、AutoCloseableを実装すればtry-with-resourcesに対応できる!
#AutoCloseableについて
閉じられるまでリソース(ファイルまたはソケットハンドルなど)を保持できるオブジェクト。
AutoCloseableオブジェクトのclose()メソッドは、リソース仕様ヘッダーでオブジェクトが宣言されているtry-with-resourcesブロックを終了すると、自動的に呼び出される。
この構造により、迅速なリリースが保証され、リソース不足の例外や、そうでなければ発生する可能性のあるエラーが回避されます。
java.langパッケージに含まれている。
Interface AutoCloseable
https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/AutoCloseable.html
try-with-resourcesでtry文が終わった時に自動でクローズ処理してもらいたい、
またクローズ時に特殊な処理を挟んでほしい対象のリソースに対してAutoCloseableインターフェースを実装する。
##AutoCloseableとCloseableについて
AutoCloseableと似て非なるものでCloseableがある。
こちらはAutoCloseableを継承したインターフェースであり、こちらはjava.ioパッケージに含まれている。
AutoCloseableは例外発生時にExceptionをスローするが、CloseableはIOExceptionをスローする。
java.ioパッケージにあるほとんどのクラスでCloseableが実装されている為、
FileOutputStreamやBufferedReaderなどのクラスはtry-with-resourcesで宣言できる。
#使用
try-with-resourcesで自動的にリソースの開放したい場合、
リソース解放時にほかの処理も加えたい場合などに使用する。
public class SampleTryWithResources {
public static void main(String[] args) {
// Closeable(AutoCloseable)を実装しているクラスを
// try-with-resourcesで宣言すると、try文終了時に自動でclose()が実行される。
try (SampleCloseAble sca = new SampleCloseAble()) {
System.out.println("Try-With-Resources開始");
System.out.println("try文実行中");
System.out.println("Try-With-Resources終了");
} catch (Exception e) {
e.printStackTrace();
}
}
}
class SampleCloseAble implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("Closeableクラスのclose()実行");
}
}
Try-With-Resources開始
try文実行中
Try-With-Resources終了
Closeableクラスのclose()実行
try文の中の処理が終了した後に実装したcloseメソッドが呼び出されている。
ただし、次のようにtry文の中で例外が発生すると、catch文の前にcloseメソッドが呼び出されることに注意すること。
public class SampleTryWithResources2 {
public static void main(String[] args) {
try (SampleCloseAble sca = new SampleCloseAble()) {
System.out.println("Try-With-Resources開始");
System.out.println("try文実行中");
throw new Exception();
} catch (Exception e) {
System.out.println("Try文例外終了");
e.printStackTrace();
}
}
}
Try-With-Resources開始
try文実行中
Closeableクラスのclose()実行
Try文例外終了
java.lang.Exception
at ...
処理の順番は
Try文の中の処理 ⇒ AutoCloseableのcloseメソッド ⇒ catch文の中の処理
となる。