HOWTO · Java
Java の assert キーワード
この記事では、Java の assert キーワードをいつどのように使用するかについて説明します。
このページの内容
Java の assert キーワードは、プログラマーが想定する条件を確認します。アサーションは JVM で既定では無効です。有効にするには、-ea を指定してプログラムを起動します。有効なアサーションの条件が false と評価されると、Java は AssertionError をスローします。条件が true なら、そのまま実行が続きます。アサーションは、開発中に成立しているはずの内部的な前提の確認に使い、アプリケーションが毎回の実行で必ず行う処理には使わないでください。
Java で assert を boolean 条件として使う
基本形は assert condition; で、condition には boolean 式を指定します。アサーションが有効な状態で式が false の場合、Java はアサーション文の位置で AssertionError をスローします。アサーションが無効なら、JVM は条件の評価も含めてアサーションをスキップします。そのため、プログラムが必要とする処理を条件式の中で実行してはいけません。
次のクラスは、件数を確認して簡単な結果を出力する、単体で実行できる例です。
public class JavaAssertCheck {
public static void main(String[] args) {
String[] names = {"John", "Mary", "David"};
assert names.length == 3;
System.out.println("Name count: " + names.length);
}
}
クラスをコンパイルしたら、java -ea JavaAssertCheck を実行してチェックを有効にします。-ea を付けずに実行すると、アサーションはスキップされます。期待する件数を配列の件数と異なる値に変更してアサーションを有効にすると、プログラムはアサーションの位置で停止し、AssertionError が発生します。
assert condition : expression で診断メッセージを付ける
失敗時に状況を伝えたい場合は、assert condition : expression を使います。式が評価されるのは、アサーションが有効で条件が false の場合だけです。その値が、発生する AssertionError の詳細メッセージになります。たとえば、assert names.length == expected : "Expected " + expected + " names, got " + names.length; は、2つの件数を示します。条件が成立した場合やアサーションが無効な場合には式が評価されないため、副作用のある式は避けてください。
assert で予期しない分岐を検出する
プログラムのロジック上、到達しないはずの実行時分岐にアサーションを置いて、その分岐を示せます。無条件の return の後に文を置くと、Java コンパイラーは到達不能な文として拒否します。そのため、コンパイラーが到達不能だと証明できない分岐の中にアサーションを置きます。
public class StatusLabel {
static String label(int status) {
if (status == 0) {
return "ready";
} else if (status == 1) {
return "busy";
} else {
assert false : "Unexpected status: " + status;
return "unknown";
}
}
public static void main(String[] args) {
System.out.println(label(0));
}
}
アサーションが有効な場合、最後の分岐に到達すると、status を状況説明として含む AssertionError が発生します。無効な場合はフォールバックの return まで実行されるため、このアサーションは診断を助けるものであり、必須の制御フローではありません。
内部不変条件の確認にアサーションを安全に使う
アサーションは、プログラム自身が成立させる不変条件を記述するのに役立ちます。たとえば、内部計算の後も値が範囲内にあることを確認できます。前提が破られたときに、開発中に原因を見つけやすくなります。
公開メソッドに渡された引数の検証にアサーションを使わないでください。呼び出し側には、JVM のオプションにかかわらず、定義された検証結果を返す必要があります。同様に、必須のアプリケーション処理をアサーションの中に入れてはいけません。アサーションが無効だと、その条件は評価されないためです。同じ理由で、アサーション式の副作用も避けてください。本番環境でも一貫した応答が必要な処理には、通常の入力検証と制御フローを使います。