J2SE 1.4まではC言語のenumに当たるものがなかったので、定数を列挙する下記のようなコードが良く書かれていた。
public class PlayingCard {
public static final int CLUBS = 0;
public static final int DIAMONDS = 1;
public static final int HEARTS = 2;
public static final int SPADES = 3;
}
上記のPlayCardクラスで定義された定数を引数に取ることを想定した下記メソッドを考える。
String suitColor(int suit) {
switch (suit) {
case PlayingCard.CLUBS:
case PlayingCard.SPADES:
return "black";
case PlayingCard.DIAMONDS:
case PlayingCard.HEARTS:
return "red";
default:
throw new IllegalArgumentException();
}
}
suitColor() はPlayCardクラスの定数以外の任意のint型の値を引数に取れる。
よって、仮に
suitColor(5);
とコーディングしても、コンパイラはエラーを検出できずに実行時に例外が発生する。
Java 5.0以降ではenum型が実装されたので PlayCard クラスの代わりenum型を使って以下のように列挙型Suitを簡潔に書ける。
public enum Suit {
CLUBS, DIAMONDS, HEARTS, SPADES
}
この Suit を使うように suitColor() を書き直すと下記のようになる。
これならば引数には列挙Suitしか取らなくなるので、不正な引数を与えた場合にコンパイルエラーとなる。
String suitColor(Suit suit) {
switch (suit) {
case CLUBS:
case SPADES:
return "black";
case DIAMONDS:
case HEARTS:
return "red";
default:
throw new AssertionError("Unknown " + suit);
}
}
enum型の実体
enum はコンパイルすると java.lang.Enum クラスを継承したクラスに変換される。Java VM からすれば enum は単なるクラスである。
Enum定数宣言(列挙子の並び)をセミコロンで終わらせた後に、通常のクラスと同じように変数やメソッドを記述できる。
swtich文での使用
enum型の定数をswitch文に使用できる。先に出てきた suitColor(Suit) メソッドのswitch文でenum型Suitを使っている。caseラベルでEnum型名を付けずにEnum定数名を単独で使っている。
Enum定数を直接書けるのは、そのEnum定数を定義しているEnum型の中とswitch文のcaseラベルだけである。
EnumMap、EnumSet
enum型をキーとするMapとしてEnumMap、enum型用のSetとしてEnumMapがある。
下記のコードは上で定義した列挙型 Day のすべての要素すべてをイテレーションするfor文と、特定の範囲をいてレーションするfor文である
すべての要素はの取得には Enum#values()を、特定の範囲の取得にはEnumSetのstaticメソッド range() を使用している。
public static void iterationTest() {
// すべての定数を表示
for (Day d: Day.values()) {
System.out.println(d.ordinal() + ":" + d);
}
System.out.println();
// 指定した範囲の定数を表示
for (Day d: EnumSet.range(Day.TUESDAY, Day.THURSDAY)) {
System.out.println(d.ordinal() + ":" + d);
}
}
出力
0:SunDAY
1:MONDAY
2:TUESDAY
3:WEDNESDAY
4:THURSDAY
5:FRIDAY
6:SATURDAY
2:TUESDAY
3:WEDNESDAY
4:THURSDAY
参考記事:Java Press Vol.38 続報 J2SE 5.0 実践チュートリアル
参考ページ:Java列挙型メモ(Hishidama's Java enum Memo)
Recent Comments