三浦ノート

自分の経験したことを検索可能にしていくブログ.誰かの役に立ってくれれば嬉しいです.

Javaの列挙型まとめ

列挙型 (enum type)

https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

https://docs.oracle.com/javase/specs/jls/se11/html/jls-8.html#jls-8.9

クラス型の特殊な1つ。型自身のstaticインスタンスをまとめて保持する。switch文の条件式に使用可能。

型の定義

{クラス修飾子} enum 型識別子 [親インターフェース] {
    列挙定数リスト;

    クラス本体定義
}

abstractfinalは付けられない。

クラス本体定義を持つ列挙定数が1つ以上含まない限りは、暗黙的にfinalになる。

入れ子列挙型は暗黙的にstatic

インスタンス化は自身の定義ブロック内での列挙定数としてのみ可能。(i.e. 外部でも内部でもnewでインスタンス化できない。同一のインスタンスが1つしかないことが保証されていて、そのようなインスタンスをシングルトンインスタンスと言う)

インターフェース実装はできるが、クラス継承はできない。

列挙型Eの直の親クラスはEnum<E>

コンストラクタは暗黙的にprivateとなる。public,protectedをつけるとコンパイルエラー 。

列挙定数

識別子 [(引数リスト)] [{クラス本体}]

自身の列挙型インスタンスを参照するもの。public static finalになる。

識別子は大文字で書くことが多い。

(引数リスト) を書くと、クラス本体定義に定義したコンストラクタに渡せる。

クラス本体を書くと、無名クラスと同様に継承ローカルクラスのインスタンス化となる。

上の列挙定数の定義は

public static final 列挙型名 識別子 = new 列挙型名([引数リスト]) [クラス本体];

と似たようなものである。前述のようにnewによるインスタンス化はできないし、toString()などObjectメソッドのオーバーライドとかも必要。

使用例

import java.time.DayOfWeek;

public class EnumType {
    public static void main(String[] arg) {
        Direction d = Direction.EAST;
        System.out.println(d.getClass()); // class main.java.tutorial.Direction
        System.out.println(d); // EAST
//        Direction d1 = new Direction(); エラー。外部でインスタンス化できない。
        Enum<Direction> superDire = d; // Directionの親クラス。
        Object objDire = d; // Object は更に親。

        // values()メソッドは列挙定数の配列を返す
        for (Direction d1 : Direction.values()){
            System.out.print(d1 + " "); // NORTH SOUTH EAST WEST
        }
        System.out.println();

        switch (d) {
            case EAST:  System.out.println("EAST"); break;
            case WEST:  System.out.println("WEST"); break;
            case NORTH: System.out.println("NORTH"); break;
            case SOUTH: System.out.println("SOUTH"); break;
        }
        // EAST

        E1 e = E1.C1;
        System.out.println(e.x); // 1
        e.x = 0;
        System.out.println(E1.C1.x); // 0
        e.f(); // a
        System.out.println(E1.C2); // C2
        System.out.println(E1.C2.x); // 2
        System.out.println(E1.C3.x); // 4
        E1.C3.f(); // b

        Days day = Days.MONDAY; // 入れ子列挙型も暗黙的にstaticなので呼べる。

        // APIにある列挙型の例
        DayOfWeek d1 = DayOfWeek.FRIDAY;
        System.out.println(d1.plus(100)); // SUNDAY
        System.out.println(DayOfWeek.of(2)); // TUESDAY
    }

    enum Days { // 入れ子列挙型
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
    }
}

enum Direction implements IF {
    NORTH, SOUTH, EAST, WEST // 列挙定数。Direction型インスタンスを参照している。
}

enum E1 {
    C1(1), C2(2), // 引数を自身のコンストラクタに渡している。
    C3(4) {// E1を継承した無名クラスのインスタンス化
        @Override
        void f() {
            System.out.println("b");
        }
    };

    // public static final E1 C4 = new E1(4); //エラー。内部でもnewでインスタンス化できない。

    int x;
    E1 (int x) {
        this.x = x;
    }

    void f() {
        System.out.println("a");
    }
}

//enum E extends C {} エラー 。クラス継承はできない。
//enum E2 extends E1 {} エラー。列挙型の継承はできない。

interface IF {}
class C {}