たとえばこんな感じで複数の処理があるとしますね。
public static void proc1(){ System.out.println("proc1"); } public static void proc2(){ System.out.println("proc2"); } public static void proc3(){ System.out.println("proc3"); }
この、proc1とproc2とproc3を、すべて実行する必要があるとします。どれかで例外が出ても残りは必ず実行できるように、と。
そうすると、それぞれtry〜catchで囲んで処理をする必要があるのですが、それを便利に記述できるイディオムがあります。
こんな感じ
try(Closeable c = () -> proc1(); Closeable c2 = () -> proc2(); Closeable c3 = () -> proc3(); ){ }
try-with-resources構文のtry句で、Closeable型の変数にLambdaを割り当てつつ所望の処理を書くという形です。
ちゃんと実行されますね。
proc3
proc2
proc1
書いたのと逆順だけど。
このとき、もしproc2で例外が出るとしますね。
public static void proc2(){ throw new RuntimeException("例外だよー"); }
それでもproc1とproc3はちゃんと実行されて、その上で例外が投げられます。
proc3
proc1
Exception in thread "main" java.lang.RuntimeException: 例外だよー
これのいいところは、複数の例外を自動でたばねてくれるところです。
proc1でも例外が出るとします。
public static void proc1(){ throw new RuntimeException("例外だよー"); }
そうすると、投げられる例外の中でこんな感じでSuppressedに他の例外がまとめられます。
proc3
Exception in thread "main" java.lang.RuntimeException: 例外だよー
at app.TWR.proc2(TWR.java:20)
at app.TWR.lambda$1(TWR.java:28)
at app.TWR$$Lambda$2/1523554304.close(Unknown Source)
at app.TWR.main(TWR.java:31)
Suppressed: java.lang.RuntimeException: これも例外だよー
ちゃんと例外を捕まえて、すべての例外を処理する場合はこんな感じになりますね。
try(Closeable c = () -> proc1(); Closeable c2 = () -> proc2(); Closeable c3 = () -> proc3(); ){ }catch(Exception e){ Stream.concat( Stream.of(e), Arrays.stream(e.getSuppressed())) .forEach(ex -> System.out.println(ex.getMessage())); }
こんな感じになります。
proc3
例外だよー
これも例外だよー
これで、確実に処理したいコードが手軽に書けますね!
注意事項
書いたのと逆順に実行されることには注意が必要です。
あと、本番コードでこんな書き方しないようにしましょう。
リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)
- 作者: Dustin Boswell,Trevor Foucher,須藤功平,角征典
- 出版社/メーカー: オライリージャパン
- 発売日: 2012/06/23
- メディア: 単行本(ソフトカバー)
- 購入: 68人 クリック: 1,802回
- この商品を含むブログ (140件) を見る