導入
Javaのswitch文は、Java 12以降の「switch式」の導入により、単なる条件分岐から、より安全で網羅的なデータ処理機構へと進化しました。しかし、現場の開発現場で意外と見落とされがちなのが「caseラベルに指定できる定数式」の厳密なルールです。本記事では、switch文のcaseにおける定数式の仕様を正しく理解し、バグを未然に防ぐための実装スキルを解説します。
基礎知識
Javaのswitch文において、caseラベルに記述できるのは「定数式(Constant Expressions)」です。具体的には、プリミティブ型、String型、enum定数、およびfinalで修飾された定数(コンパイル時に値が確定するもの)を指します。
重要なのは、コンパイル時に値が解決できないものは、たとえfinalであってもcaseには書けないという点です。また、近年では「instanceof パターンマッチング」が導入され、型の比較もswitchで行えるようになりましたが、定数式と型判定を混同するとコンパイルエラーの原因となります。
実装/解決策
実務で最も注意すべきは、「定数式に算術演算やビット演算を含める場合」です。例えば、定数同士の加算やビットシフトは定数式として認められますが、メソッド呼び出しや非定数変数の参照は認められません。
安全なコードを書くための鉄則は以下の通りです。
1. 定数は必ず「static final」で定義する。
2. 複雑な条件判定はswitch内で行わず、事前計算した定数を使用する。
3. パターンマッチングを利用する場合、定数と型判定の順番に注意する。
サンプルプログラム
以下のコードは、定数式を用いたswitch式の標準的な実装例です。
import java.util.Objects;
public class SwitchExample {
// コンパイル時に値が確定する定数
private static final int BASE_CODE = 100;
private static final int OFFSET = 50;
public static void main(String[] args) {
int input = 150;
// switch式を用いた値の評価
String result = switch (input) {
// 定数式(加算)はコンパイル時に評価されるため使用可能
case BASE_CODE + OFFSET -> “一致: 150”;
// ビット演算による定数も使用可能
case 1 << 8 -> “一致: 256”;
// デフォルトケースは必須(網羅性の保証)
default -> “その他”;
};
System.out.println(result);
}
}
応用・注意点
現場で陥りやすい罠として、「instanceof パターンマッチング」との併用があります。Java 17以降のswitchでは以下のような記述が可能ですが、注意が必要です。
switch (obj) {
case String s && s.startsWith(“A”) -> … // これは「ガード条件」
case Integer i -> …
}
注意点として、caseラベルに定数式(100など)とパターン(Integer i)を混在させる場合、コンパイラは型の網羅性を厳密にチェックします。
また、定数式として「null」を扱う場合は注意が必要です。Javaのswitch文(特にswitch式)ではnullをcaseに書くことは可能ですが、古いバージョンのJavaとの互換性や、NullPointerExceptionを避けるため、switchに渡す変数は常にObjects.requireNonNull()などでチェックする癖をつけておくことが、シニアエンジニアとしての推奨プラクティスです。

コメント