概要
業務コードで「状態」や「区分」を扱うとき、文字列定数や int 定数を並べて管理しているプロジェクトは少なくありません。しかし定数が増えるほどタイポや比較ミスが入り込みやすくなり、保守コストが静かに膨らんでいきます。Java の Enum はこうした問題に対する標準的な回答で、型安全な定数グループを定義し、switch 文で網羅性チェックまで得られます。この記事では、Enum の基本的な定義方法から values() による全要素取得、valueOf() による文字列変換、name() と ordinal() の違いと注意点、そして switch 文・switch 式での分岐パターンまでを扱います。Java 8 の従来型 switch と Java 14 以降の switch 式の書き分けも示しながら、現場で迷いやすいポイントを整理します。
使いどころ
注文ステータス(未処理・処理中・完了・キャンセル)を Enum で定義し、画面表示やバッチ処理の分岐に使う
曜日や休日種別を Enum にまとめ、勤怠管理システムの休日判定ロジックを型安全に記述する
CSV 取込時に文字列カラムを valueOf で Enum に変換し、不正値を早期に検出する
コード例
public class EnumBasicExample {
// 注文ステータスの Enum
enum OrderStatus {
PENDING, // 未処理
PROCESSING, // 処理中
COMPLETED, // 完了
CANCELLED; // キャンセル
public boolean isTerminal() {
return this == COMPLETED || this == CANCELLED;
}
}
public static void main(String[] args) {
// 基本操作: name(), ordinal(), values(), valueOf()
var status = OrderStatus.PROCESSING;
System.out.println("名前: " + status.name()); // PROCESSING
System.out.println("順序: " + status.ordinal()); // 1
// values() で全要素を取得
for (var s : OrderStatus.values()) {
System.out.println(s.name() + " (ordinal=" + s.ordinal() + ")");
}
// valueOf() で文字列から変換
var fromStr = OrderStatus.valueOf("COMPLETED");
System.out.println("文字列から変換: " + fromStr);
// == で比較(equals() より安全)
System.out.println(status == OrderStatus.PROCESSING); // true
// switch 式で分岐(Java 14+)
String label = switch (status) {
case PENDING -> "注文待ち";
case PROCESSING -> "処理中";
case COMPLETED -> "完了";
case CANCELLED -> "キャンセル";
};
System.out.println("ステータス: " + label);
System.out.println("終端状態: " + status.isTerminal()); // false
}
}Version Coverage
switch 式(-> 記法)が使え、break 不要で値を返せる。var による型推論も可能。網羅性チェックがコンパイル時に効く。
// Java 17: switch 式(-> 記法、break 不要)
var status = OrderStatus.PROCESSING;
String label = switch (status) {
case PENDING -> "注文待ち";
case PROCESSING -> "処理中";
case COMPLETED -> "完了";
case CANCELLED -> "キャンセル";
};Library Comparison
注意点
valueOf() に存在しない文字列を渡すと IllegalArgumentException が発生する。外部入力を変換する場合は try-catch か事前チェックが必要
ordinal() の値は定義順に依存するため、DB 保存やシリアライズに使うと定義順の変更でデータが壊れる。永続化には name() か明示的なコード値を使うこと
switch 文で Enum を扱う場合、case ラベルに Enum 名だけを書く(Color.RED ではなく RED)。修飾名を書くとコンパイルエラーになる
Enum の == 比較は equals() と同じ結果を返し、null に対して NullPointerException を起こさない点で == のほうが安全。ただし null チェック自体は省略しないこと
FAQ
== を使うのが一般的です。Enum はシングルトンが保証されており、== で正しく比較できます。null に対して NullPointerException を起こさない点でも == が安全です。
言語仕様上の制限はありません。ただし、Enum に過度にロジックを詰め込むと責務が膨らむので、複雑な処理は別クラスに切り出す設計が実務では好まれます。
標準の valueOf は大文字小文字を区別します。大文字小文字を無視したい場合は、入力値を toUpperCase() してから渡すか、独自の fromName メソッドを用意してください。