Javaにおけるtry-with-resourcesの主な目的は、リソースを自動的かつ適切に解放することです。この構文がJava 7で登場する以前は、プログラマーはfinallyブロック内で手動でリソースを閉じなければなりませんでした。これによりコードの重複やバグが発生していました。
Java 6以前では、リソース(オープンファイル、ストリーム、接続)を手動でfinallyを通じて管理する必要があり、これがしばしばメモリリークを引き起こしました。
手動で書かれたリソースを閉じるコードは、特に複数の例外や複雑なcatchブロックの階層を扱う際にバグの原因となります。エラー時にclose()が呼ばれる保証はありません。
Java 7からは、try-with-resources構文が導入され、AutoCloseableインターフェースを実装する各リソースに対してclose()メソッドが自動的に呼び出されることが保証されます。
コードの例:
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) { String line = reader.readLine(); System.out.println(line); } catch (IOException e) { e.printStackTrace(); } // readerは自動的に閉じられます
主な特徴:
AutoCloseableインターフェースを実装しているオブジェクトのみがtry-with-resourcesで使用できます。質問1: リソースはtry-with-resourcesのためにどのインターフェースを実装する必要がありますか?
AutoCloseable。このインターフェース(またはCloseable)を実装するオブジェクトは、構文内で使用できます。
質問2: 複数のリソースがある場合、どの順序で閉じられますか?
リソースは宣言の逆順(スタック-LIFO)で閉じられます:
try (A a = new A(); B b = new B()) { ... } // b.close() が最初に呼ばれ、その後 a.close() が呼ばれます
質問3: AutoCloseableの実装がないネットワーク接続のような非標準オブジェクトに対してtry-with-resourcesを使用できますか?
いいえ、ただし、独自のクラスでAutoCloseableを手動で実装することができます。その後、オブジェクトはtry-with-resourcesに対応できるようになります。
開発者がJDBC ConnectionとStatementを手動でfinallyを通じて閉じていました。2つ目の例外が発生した場合、Statementの閉鎖が行われず、接続が「ハング」し、エラーを隠しました。
利点:
欠点:
ファイルの読み込みモジュールでtry-with-resourcesを導入した後、すべてのストリームが自動的に閉じられ、コードが大幅に短くなり、ファイルディスクリプタのリークバグが解消されました。
利点:
欠点: