Java 8で導入されたラムダ式またはメソッド参照と、Java 7以降のtry-with-resources構文を組合せて、任意のオブジェクトに対するスコープガード処理を記述する方法。
// Java 7以降 class X implements AutoCloseable { // AutoCloseable#closeを実装したクラスが必要 void close() { ... } } try (X obj = new X(...)) { // ... } // 上記スコープを抜けるときにobj.close()が呼ばれる
// Java 8以降:メソッド参照版 class X { // メソッドシグニチャが"void メソッド名()"であればOK void dispose() { ... } } X obj = new X(...); try (AutoCloseable ac = obj::dispose) { // ... } catch (Exception e) { ... } // 上記スコープを抜けるときにobj.dispose()が呼ばれる
// Java 8以降:ラムダ式版 class X { int method(int a1) { ... } } X obj = new X(...); // 注意:以降での変数objへの再代入は禁止! try (AutoCloseable ac = () -> obj.method(42)) { // ... } catch (Exception e) { ... } // 上記スコープを抜けるときにobj.method(42)が呼ばれる
ラムダを用いた上記例では、ラムダ式中でキャプチャするローカル変数objを “実質的にfinal(effectively final)” とするため、変数定義以降での再代入を行ってはならない。(もしくは単にfinal X obj = ...;
で変数定義する)
メモ:AutoCloseable#closeメソッドはthrows Exception
指定がついているため、try-with-resources構文側にcatch (Exception e) { ... }
が必須になり煩雑。下記のようなインタフェースを用意してAutoCloseable
代用とすれば回避可能。
interface NoThrowCloseable extends AutoCloseable { void close(); }
関連URL