Enum(Java)
TypesafeなEnum
Java5.0より、Typesafe(タイプセーフ;型に関して安全)なEnumという型が追加されました。プログラム(クラス)の状態などを保持するための「列挙型」と呼ばれますが、ちょっと変わった動きをします。
簡単なEnumのサンプルプログラム
まずは、簡単なサンプルを見ながら、Enumの挙動を確認してしましょう。package test;
public class ExampleEnum1 {
public enum Status {HOP,STEP,JUMP} // (A)
public static void main(String[] args){
System.out.println(Status.HOP); // (B)
System.out.println(Status.STEP);
System.out.println(Status.JUMP);
// 比較(条件分岐)のテスト1
if(Status.HOP.equals("HOP")){ // (C)
System.out.println("check if : true");
}else{
System.out.println("check if : false");
}
// 比較(条件分岐)のテスト2 // (D)
if(Status.HOP.toString().equals("HOP")){
System.out.println("check if : true");
}else{
System.out.println("check if : false");
}
// 比較(条件分岐)のテスト3
for(Status sts : Status.values()) // (E)
switch(sts){
// case要素として、Enumをつかうと、Status.を省略できる。
case HOP : //(F)
System.out.println("STATUS: "+sts);
break;
case STEP :
System.out.println("STATUS: "+sts);
break;
case JUMP :
System.out.println("STATUS: "+sts);
break;
}
}
}
}
これを実行すると次の結果が得られます。
HOP
STEP
JUMP
check if : false
check if : true
STATUS: HOP
STATUS: STEP
STATUS: JUMP
(A)がEnumの定義になります。位置に注意してもらいたいのですが、mainメソッドの外に定義されています。
形式は、
修飾子 enum Enum名称 {文字列1、文字列2、文字列3}という形式です。
これは、Enumを継承して、Enum名称のクラスを作り、そのオブジェクトとして文字列1、2、3を生成する。
という特殊な意味を持ちます。EnumのAIPドキュメントはこちら。
この例では、Enumを継承してStatusクラスを作り、そのオブジェクトとしてHOP、STEP、JUMPを作るということを意味しています。
(B)は、列挙したHOP、STEP、JUMPオブジェクトへのアクセス方法を示しています。「クラス名称.オブジェクト名称」がアクセス方法となります。
このことから、(A)の宣言をすると、Statusクラスが作成される際に、その内部にstaticなHOP、SEP、JUMPというStatusオブジェクトが保持されることが分かります。
(また、Enumを継承してStatusが作成される際、Enumクラスには定義されていないStatus[] values()メソッドと、Status valueOf(String _str)メソッドが追加されます。これについては、こちらのHPを参照。)
(C)と(D)を比較してください。ともにStringである"HOP"との比較結果を意味しています。
(C)はfalse、(D)はHOPオブジェクトのtoString()メソッドを呼ぶことでtrueとなっています。
「クラス名称.オブジェクト名称」は文字列ではなくて、オブジェクトであることを認識することは重要です。
(E)はswitch文に適用した例です。
この場合には(F)のように、「オブジェクト名」だけを記述することができます。上の例では、Status.values()でStatusオブジェクトの配列を取り出し、拡張for文によって順に取り出していきます。
Enumの拡張
上で(A)で定義されたStatusは、Enumを継承したクラスでHOP、STEP、JUMPはそのオブジェクトであると説明しました。以下ではこれを拡張したサンプルを書いてみましょう。package test;
public class ExampleEnum2 {
public enum Status {HOP("ホップ"),STEP("ステップ"),JUMP("ジャンプ"); // (A)
private final String str; // (B)
Status(String _str){ // (C)
this.str=_str;
}
public String say(){ // (D)
return str;
}
} // (E)
public static void main(String[] args){
// 拡張したメソッドを使う
for(Status sts : Status.values())
System.out.println(sts.say()); // (F)
}
}
(A)から(E)までがStatusオブジェクトを拡張した部分です。
(C)でStatusのコンストラクタをオーバーロードして、引数に文字列を取るようにします。それを(B)で定義したプロパティーに格納します。
このため、(A)のHOP、STEP、JUMPにはString型の引数を与えるよう変更しています。
(D)は新しく追加したメソッドで、戻り値として、コンストラクタでセットしたプロパティー(String)を返します。
mainメソッドの(F)において、このメソッドを使って、結果を出力します。
実行した結果は狙い通り
ホップとなります。
ステップ
ジャンプ
Typesafeとは
Java5.0で導入されたEnumは、わざわざ「Typesafe(型について安全)なEnum」と呼ばれます。これは、enum型として定義した変数(上の例ではStatus)に、他の型(プリミティブ型、参照型)を入れるとコンパイルエラーになることを意味しています。(eclipseでは赤くなります)
つまり、Genericsと同じメリット、「実行時エラーをコンパイルエラーにする」ことで、バグを早期に潰すことを意味しています。
2007年02月28日(水) 16:17:34 Modified by wanderingse