実行時例外スローを式に
Javaのthrow文は文なので、使い勝手が悪いことがあります。
そこで、式にしてみます。(検査例外は面倒なので実行時例外限定)
やり方
実行時例外を引数にとり、それをスローするだけのpublic staticメソッドを用意します。
どの文脈でも使えるように戻り値型をジェネリックにしておきます。
以上。
public static <A> A throwR(final RuntimeException e) { throw e; }
使いどころ
常に例外をスローする式だけでは、プログラムを異常終了させるだけです。
条件演算子(いわゆる三項演算子)やいわゆるショートサーキット演算子では一部の部分式しか評価されないので、そこに例外をスローする式を挿入します。
これで事前条件のアサーションに使えます。
まずは文が使えない あるいは制限されている箇所です。
また、制御構造を変えるのが面倒なときに使えます。
- 条件演算子をネストしていて、各条件の評価を活かしたい時
使用例
package test; public class ThrowTest { // 実行時例外をスローする public static <A> A throwR(final RuntimeException e) { throw e; } static class C { private final String str; public C(final String str) { this.str = str; } } static class C2 extends C{ public C2(final String str) { // superコンストラクタ呼び出し前に例外 super(str != null ? str : ThrowTest.<String> throwR( new NullPointerException("arg is null"))); } private static int instanceSeq = 0; private static final int MAX_SEQ = 10; // フィールド初期化前に例外 private final int seq = instanceSeq <= MAX_SEQ ? instanceSeq++ : ThrowTest.<Integer> throwR(new IllegalStateException("too big seq")); private String message() { // 三項式の最後に例外を投げたくなったら return cond1() ? "one" : cond2() ? "two" : cond3() ? "three" : ThrowTest.<String> throwR(new IllegalStateException("unexpected")); } private static boolean cond1() { return false; } private static boolean cond2() { return false; } private static boolean cond3() { return false; } } }
おまけ
実行時例外をスローする式をジェネリックにしたので、throwに渡せます。実型引数を検査例外にすると例外が予測しづらくなります。
throw ThrowTest.<ParseException> throwR(new NullPointerException("null"));