列挙型(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("平日"); } } }
出力例:
週末の前日!