Javaにおける列挙型(enum)の詳細ガイド

Javaの列挙型(enum)は、固定された有限個のインスタンスを持つ特殊なクラスです。通常のクラスとは異なり、インスタンスの数を制限できるため、状態やカテゴリを表現するのに適しています。以下では、基本的な使い方から高度な機能まで解説します。

定義の基本

public enum Orientation {
    NORTH, SOUTH, EAST, WEST;
}

キーワードはenum(小文字)であり、Enumではありません。各定数(インスタンス)は列挙子(enum constants)と呼ばれ、最後のセミコロンは定義の終了を示します。列挙子が複数ある場合はカンマで区切り、最後の後ろにセミコロンを置きます。列挙子のみの場合はセミコロンを省略可能ですが、可読性のために推奨されません。

列挙型の使用

public class TestOrientation {
    public static void main(String[] args) {
        Orientation dir = Orientation.EAST;
        System.out.println(dir); // EAST
    }
}

列挙子はインスタンスとして扱われるため、直接代入や比較が可能です。

switch文での利用

public class SwitchExample {
    public static void main(String[] args) {
        Orientation current = Orientation.NORTH;
        switch (current) {
            case NORTH:
                System.out.println("北");
                break;
            case SOUTH:
                System.out.println("南");
                break;
            case EAST:
                System.out.println("東");
                break;
            case WEST:
                System.out.println("西");
                break;
            default:
                System.out.println("不明");
        }
    }
}

注意点:caseラベルには列挙型名(例:Orientation.NORTH)は記述せず、列挙子名だけを書きます。コンパイラがswitchの変数の型から自動的に判別します。

すべての列挙型はjava.lang.Enumを継承

列挙型は暗黙的にjava.lang.Enum<E>を継承しています。そのため、以下の共通メソッドが利用できます。

  • int ordinal() – 宣言された順序(0始まり)
  • String name() – 列挙子の名前をそのまま返す
  • String toString() – デフォルトはname()と同じ
  • int compareTo(E o) – ordinalに基づく比較
  • boolean equals(Object obj) – 同一列挙子か判定
  • int hashCode() – ハッシュコード

静的メソッドvalueOf(Class, String)も継承されますが、後述の自動生成メソッドが便利です。

列挙型のコンストラクタ

列挙型にコンストラクタを定義できますが、アクセス修飾子はprivateのみ許可されます。外部からインスタンス化できないためです。

public enum Direction {
    NORTH("北"), SOUTH("南"), EAST("東"), WEST("西");

    private String japaneseName;

    Direction(String japaneseName) {
        this.japaneseName = japaneseName;
    }

    public String getJapaneseName() {
        return japaneseName;
    }
}

列挙子を宣言するときに引数を渡します。各列挙子はこのコンストラクタで初期化されます。

列挙型にフィールドやメソッドを持たせる

通常のクラスと同様に、メソッド、静的フィールド、静的メソッドも定義可能です。

public enum Operation {
    PLUS, MINUS, TIMES, DIVIDE;

    public double apply(double x, double y) {
        switch (this) {
            case PLUS:   return x + y;
            case MINUS:  return x - y;
            case TIMES:  return x * y;
            case DIVIDE: return x / y;
            default:     return Double.NaN;
        }
    }
}

各列挙子に関連する振る舞いをカプセル化できます。

列挙型に抽象メソッドを定義する

列挙型自体に抽象メソッドを宣言できます。この場合、各列挙子は匿名クラスを使ってその抽象メソッドを実装する必要があります。

public enum TrafficLight {
    RED {
        @Override
        public TrafficLight next() {
            return GREEN;
        }
    },
    GREEN {
        @Override
        public TrafficLight next() {
            return YELLOW;
        }
    },
    YELLOW {
        @Override
        public TrafficLight next() {
            return RED;
        }
    };

    public abstract TrafficLight next();
}

これはポリモーフィズムを列挙型に導入する強力な方法です。

自動生成される2つの静的メソッド

すべての列挙型にはコンパイラによってvalues()とvalueOf(String)が自動追加されます。これらはEnumクラスに存在しない特殊なメソッドです。

public class MethodDemo {
    public static void main(String[] args) {
        Orientation[] all = Orientation.values();
        for (Orientation o : all) {
            System.out.println(o);
        }

        Orientation found = Orientation.valueOf("SOUTH");
        System.out.println(found); // SOUTH
    }
}
  • values() – 宣言順の配列を返す
  • valueOf(String) – 指定された名前の列挙子を返す(存在しない場合はIllegalArgumentException)

これらのメソッドはリフレクションなしで安全に列挙子を操作できます。

タグ: Java 列挙型 Enum switch文 abstract method

10月9日 22:16 投稿