Java の enum

イマドキの Java には enum があるんですよ実は、という話。
知ってるよそんなこと!な人は読むまでもないかも。

enum って?

列挙型のこと。C とか C++ とか C# とかでおなじみのアレ。
単純な enumJava でもこれらの言語の enum と同じような記述になるけど、これらの言語の enum が整数型をベースにしているのに対して、Java ではオブジェクトをベースにしている点が異なる。
まぁその話は後ほど・・・

単純な enum


 enum C C++  C# 
// 信号機の色
enum SignalColor { RED, BLUE, YELLOW }


enum SignalColor { RED, BLUE, YELLOW, }


enum SignalColor { RED, BLUE, YELLOW; }


enum SignalColor { RED, BLUE, YELLOW, ; }


使
static String colorName(SignalColor color) {
    switch (color) {
    case RED: return "赤";
    case BLUE: return "青";
    case YELLOW: return "黄";
    default: throw new IllegalArgumentException();
    }
}

public static void main(String[] args) {
 System.out.println(colorName(SignalColor.BLUE));
}

case  SignalColor 
switch  case  main 
colorName  null  NullPointerException 
 IllegalArgumentException  NullPointerException  jad  javap 

フィールドを持った enum


Java  enum 
enum SignalColor {
    RED, BLUE, YELLOW;
    String colorName;
}


static String colorName(SignalColor color) {
    return color.colorName;
}

public static void main(String[] args) {
    SignalColor.RED.colorName = "赤";
    SignalColor.BLUE.colorName = "青";
    SignalColor.YELLOW.colorName = "黄";
    System.out.println(colorName(SignalColor.BLUE));
}


enum SignalColor {
    RED("赤"),
    BLUE("青"),
    YELLOW("黄");
    public final String colorName;
    private SignalColor(String colorName) {
        this.colorName = colorName;
    }
}


*1
 public  protected  package private private 



使
static String colorName(SignalColor color) {
    return color.colorName;
}

public static void main(String[] args) {
    System.out.println(colorName(SignalColor.BLUE));
}




Java  enum  enum 
class SignalColor {
    private final String colorName;
    private SignalColor(String colorName) { this.colorName = colorName; }
    
    public static final SignalColor RED = new SignalColor("赤");
    public static final SignalColor BLUE = new SignalColor("青");
    public static final SignalColor YELLOW = new SignalColor("黄");
}

*2

メソッドを持った enum


Java  enum 
enum SignalColor {
    RED, BLUE, YELLOW;
    String colorName() {
        switch (this) {
        case RED: return "赤";
        case BLUE: return "青";
        case YELLOW: return "黄";
        default: throw new IllegalStateException();
        }
    }
}
public static void main(String[] args) {
    System.out.println(SignalColor.BLUE.colorName());
}

enum  switch colorName  NullPointerException  (Java  this  null )



enum SignalColor {
    RED("赤"),
    BLUE("青"),
    YELLOW("黄");
    private final String colorName;
    SignalColor(String colorName) {
        this.colorName = colorName;
    }
    String colorName() { return colorName; }
}

 ()
列挙子ごとにオーバーライド

列挙子ごとにメソッドをオーバーライドすることもできる。

enum SignalColor {
    RED {
        @Override
        String colorName() { return "赤"; }
    },
    BLUE {
        @Override
        String colorName() { return "青"; }
    },
    YELLOW {
        @Override
        String colorName() { return "黄"; }
    };
    String colorName() { throw new UnsupportedOperationException(); }
}
抽象メソッドを持った enum


enum SignalColor {
    RED {
        @Override
        String colorName() { return "赤"; }
    },
    BLUE {
        @Override
        String colorName() { return "青"; }
    },
    YELLOW {
        @Override
        String colorName() { return "黄"; }
    };
    abstract String colorName();
}


interface Color { String colorName(); }

enum SignalColor implements Color {
    RED {
        public String colorName() { return "赤"; }
    },
    BLUE {
        public String colorName() { return "青"; }
    },
    YELLOW {
        public String colorName() { return "黄"; }
    }
}


クラス内に記述する enum について

あるクラスに enum を含めた場合、static を付けても付けなくても static とみなされる。
なので、外側の this を使うことは出来ない。

enum で使用できるメソッドの便利な使い方

values()

Enum クラスに定義されていないので見落としがちだが、各 enum には static メソッドとして values メソッドが定義される。
このメソッドは、全ての列挙子を含む配列を記述された順番で返すので、数値から列挙子オブジェクトへの変換に使用できる。

static SignalColor valueOf(int i) {
    return SignalColor.values()[i];
}

public static void main(String[] args) {
    SignalColor c = valueOf(1);
    System.out.println(c.name());   // BLUE
}
valueOf(String name)

これも Enum クラスに定義されていないが、各 enum には static メソッドとして文字列のみを引数に取る valueOf メソッドが定義される。
このメソッドは、指定された名前を持つ列挙子オブジェクトを返す。

public static void main(String[] args) {
    SignalColor c = SignalColor.valueOf("BLUE");
    System.out.println(c.name());   // BLUE
}

何か忘れてない・・・?


C enum 使

#include <stdio.h>

typedef enum hoge {
    HOGE_1 = 1,
    HOGE_2 = 2,
    HOGE_3 = 4,
    HOGE_4 = 8
} hoge;

void f(hoge h)
{
    if (h & HOGE_2) puts("hoge 2");
    if (h & HOGE_3) puts("hoge 3");
}

int main()
{
    f(HOGE_3);
    f(HOGE_1 | HOGE_3);
    return 0;
}

2
 Java  enum EnumSet 使
enum Hoge {
    HOGE_1, HOGE_2, HOGE_3, HOGE_4
}

static void f(EnumSet<Hoge>h) {
    if (h.contains(Hoge.HOGE_2)) System.out.println("hoge 2");
    if (h.contains(Hoge.HOGE_3)) System.out.println("hoge 3");
}

public static void main(String[] args) {
    f(EnumSet.of(HOGE_3));
    f(EnumSet.of(HOGE_1, HOGE_3));
}

Java  enum 便 null 

*1:なので、今までの例でも中が空の小括弧を記述することが可能

*2:実際には Enum クラスを継承したりしているので、enum を使った方が色々できる