列挙型(enum)とは、あらかじめ決められた選択肢の中から1つを選ぶ必要がある場面で使用される特別なデータ型です。Javaではenumをうまく活用すると、コーディングミスの防止や可読性の向上、コード全体の保守性を高めることができます。
enum Season {
SPRING, SUMMER, FALL, WINTER;
}

「曜日」「四季」のように、選択肢が限られているものを表現するために使用されるため、enumは「選択肢の管理者」のような役割を果たします。
+---------------------+ | enum Day | <-- 列挙型 (enum) +---------------------+ | - MONDAY | <-- 定数1 | - TUESDAY | <-- 定数2 | - WEDNESDAY | <-- 定数3 | - THURSDAY | <-- 定数4 | - FRIDAY | <-- 定数5 | - SATURDAY | <-- 定数6 | - SUNDAY | <-- 定数7 +---------------------+
Javaの列挙型(enum)とは?
enumは、決まった範囲の値を1つの型としてまとめる役割を持つデータ型の一種(厳密にはjava.lang.Enumを継承したクラスとして扱われます)。
具体的な例として、曜日(MONDAY、TUESDAY)や四季(SPRING、SUMMER)を扱う際に便利なデータ型です。
例え話:レストランの注文で・・・
- レストランでは「ラーメン」「カレー」「ハンバーグ」など、メニューから選んで注文します。これ以外の注文が来ても対応できません。同様に、
enumを使えば、プログラム内で定義した選択肢以外の無効な値を防ぐことができます。
enumを使わない場合の問題
選択肢を文字列(String)で扱う場合、タイプミスや異なる表記によるエラーが発生しやすくなります。以下の例を見てください。
// Stringを使った例(エラーの原因) String day = "Mondai"; // スペルミスによるバグ // enumを使った例(安全) Day day = Day.MONDAY; // 決まった選択肢だけが使用可能
要するにタイプミスやコーディングミスを制限するために役立つのがenumのもう1つの側面でもあります。
enumの基本的な使い方:構文ルール
以下のように、Javaのenumは特定の選択肢を定数として宣言します。
public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
ポイント enumの基本的な性質:不変性
- 要素の追加・削除不可:
enumの宣言後に要素を追加したり削除することはできません。 - 要素の再代入不可:プログラムの実行中に
enumの要素を新しい値に変更することはできません。 - 定数はすべて暗黙的に
finalかつstatic:そのため、インスタンス化も変更もできません。
public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}
// 以下のコードはコンパイルエラーになる
Day today = Day.MONDAY;
// today = "Holiday"; // エラー: 型が一致しない

※enumの要素は型名.要素名で呼び出します(例:Day.MONDAY)。
理由1:不変性による安全性
enumを使うことで、プログラムが予期せぬ変更を受けないようにすることができます。
例:曜日が動的に変わることは現実的にないため、不変性が理にかなっています。
理由2:メモリの効率化
enumの各要素はJavaによってシングルトン(Singleton)として管理され、1つのインスタンスが再利用されます。そのため、新たなインスタンスを作成したり、既存の要素を書き換える必要がありません。
enum(列挙型)はクラスの一種です。実際、enumを定義するとコンパイラはjava.lang.Enumを継承したクラスとして扱います。例えば以下のように定義すると・・・
public enum Color { RED, GREEN, BLUE; }
これはコンパイラによって下記のようなクラスに変換されます。
public final class Color extends java.lang.Enum<Color> {
public static final Color RED = new Color("RED", 0);
public static final Color GREEN = new Color("GREEN", 1);
public static final Color BLUE = new Color("BLUE", 2);
private static final Color[] $VALUES = { RED, GREEN, BLUE };
private Color(String name, int ordinal) {
super(name, ordinal);
}
public static Color[] values() {
return $VALUES.clone();
}
public static Color valueOf(String name) {
return Enum.valueOf(Color.class, name);
}
}
extends Enum<Color>:共通処理(name(),ordinal(),compareTo()など)をEnumクラスから継承。- 定数ごとに
new Color("NAME", 番号)でインスタンス化。 $VALUES配列で全定数を保持。
- 基底クラス
java.lang.Enumの役割name(): 定数の文字列表現ordinal(): 宣言順の添字compareTo(): 宣言順比較toString(): デフォルトでname()を返す
- 自動生成される静的メソッド
values():$VALUESをclone()して返却(外部から配列を書き換えられないように)valueOf(String): 名前一致で定数を取得。存在しないとIllegalArgumentExceptionを投げる。
- ユーザー定義の要素
- 独自フィールドやメソッドを
enum内に記述可能。 - たとえば、
RED(255,0,0)のようにコンストラクタ引数を持たせ、RGB値を保持できる。
- 独自フィールドやメソッドを
ポイント enumの特徴まとめ
| 項目 | 説明 |
|---|---|
| クラスの一種 | Enumは内部的にはクラス(ただし継承はできない) |
| 固定値の集合 | 決まった値(定数)を列挙するのに使う |
| メソッド定義可能 | メソッドやフィールドを追加できる |
| インスタンス生成 | 自動で定義された値分だけ生成され、newで追加は不可 |
enumの活用例
enumの要素は定数(staticなインスタンス)として定義されているので、クラス名.要素名の形で呼び出せます。
// 列挙型(enum)の定義
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}
public class EnumExample {
public static void main(String[] args) {
// 今日の曜日を設定
Day today = Day.MONDAY;
// 曜日に応じた条件分岐
if (today == Day.MONDAY) {
System.out.println("今日は月曜日です!");
} else {
System.out.println("今日は月曜日ではありません。");
}
}
}
出力例:
今日は月曜日です!

enumもクラスの一種!そして、enumの各定数は自動的にstatic finalなインスタンスとして生成される!
という点だけ頭に入れておけば基本的には自由に使いこなすことができるはずです。
enumの応用例
ここからは、enumの応用編です。より実践に近づけながら解説します。
enumにメソッドを追加する
enumは定数の集合だけでなく、メソッドを持たせることで、より柔軟な使い方が可能です。
参考 メソッドとは?

enumにメソッドを持たせる理由はなんでしょうか?
例えば「四季」や「状態」を表すenumがあったとしましょう。各季節に「気候の説明」を持たせたい場合、ただの定数ではそれを表現するのは難しいです。ここで、メソッドを使えば、それぞれの要素に必要な情報を持たせ、簡単に取得できるようになります。
// enumの定義:四季に説明を持たせる
enum Season {
SPRING("暖かい"),
SUMMER("暑い"),
FALL("涼しい"),
WINTER("寒い");
private final String description; // 各要素の説明を保持するフィールド
// コンストラクタ:各要素を初期化
Season(String description) {
this.description = description;
}
// 説明を取得するメソッド
public String getDescription() {
return description;
}
}
public class EnumMethodExample {
public static void main(String[] args) {
// SUMMERの説明を取得
Season currentSeason = Season.SUMMER;
System.out.println("今の季節は " + currentSeason + " で、" + currentSeason.getDescription() + "です。");
}
}
出力結果:
今の季節は SUMMER で、暑いです。
enumの内部動作
enumは、内部的にクラス(参考 クラスとは?)として実装され、各要素はシングルトンインスタンスとして生成されます。つまり、同じenum要素を比較する際に==を使うことができ、常に正しい比較が保証されます。
1. enumがクラスとして実装されるとは?
Javaでは、enumはコンパイル時に特別なクラスとして変換されます。これは、各enum要素が通常のクラスインスタンスとして扱われるという意味です。しかし、開発者が自分でインスタンスを生成したり変更することはできません。
enumの内部クラス構造イメージ
以下は、enumが内部的にどのような形でクラスとして扱われるかをイメージ化したものです。
// 実際にはJavaコンパイラによってこのようなクラスに変換される
public final class Day extends Enum<Day> {
public static final Day MONDAY = new Day("MONDAY", 0);
public static final Day TUESDAY = new Day("TUESDAY", 1);
// 他の曜日も同様に定義
private Day(String name, int ordinal) {
super(name, ordinal);
}
}
2. シングルトンパターンの適用
- シングルトンパターンは、あるクラスのインスタンスが1つだけ存在することを保証するデザインパターンです。
enumでは、このシングルトンの特性が自動的に適用されます。
enum要素はシングルトン
enumの各要素(例:MONDAY、TUESDAY)は、プログラム全体で一度だけ生成されるインスタンスです。これにより、同じ要素同士を比較するときに==演算子を使って正しく比較できるのです。
3. ==演算子による比較の正しさ
通常、Javaでは==演算子はオブジェクトの同一性(同じインスタンスかどうか)をチェックします。例えば、newキーワードで作成したオブジェクト同士を==で比較すると、異なるインスタンスなのでfalseになります。
例:newで作成したオブジェクトの比較
String a = new String("Hello");
String b = new String("Hello");
System.out.println(a == b); // false

上記の例では、aとbは同じ内容でも、異なるインスタンスなのでfalseになります。
enumでの比較
しかし、enumの場合、各要素はシングルトンとして管理されているため、同じenum要素は常に同じインスタンスです。
Day day1 = Day.MONDAY; Day day2 = Day.MONDAY; System.out.println(day1 == day2); // true
ポイント enumの内部動作
- 各要素は
static finalなインスタンスとして扱われます。 - Javaコンパイラは
enumをクラスとして変換し、最適化します。 ordinal()メソッドを使うと、要素のインデックスを取得できますが、順序に依存しない設計が推奨されます。
実務でのenumの活用例
プロジェクトの進捗状況の管理
public enum Status {
PENDING, IN_PROGRESS, COMPLETED
}
プロジェクトの進捗を管理する際、enumを使って状態を表現することで、管理を簡潔にします。
Status projectStatus = Status.IN_PROGRESS;
if (projectStatus == Status.COMPLETED) {
System.out.println("プロジェクトが完了しました!");
}
switch文との連携
switch文(参考 switch文の基本)とenumの組み合わせは、条件分岐を簡潔かつ可読性高く実装するのに有効です。
public class EnumSwitchExample {
public static void main(String[] args) {
Day day = Day.FRIDAY;
switch (day) {
case MONDAY:
System.out.println("仕事が始まる日");
break;
case FRIDAY:
System.out.println("週末の前日!");
break;
default:
System.out.println("平日");
}
}
}
出力例:
週末の前日!
