記事ディレクトリ
列挙する
1.列挙の背景と定義
列挙型は、JDK1.5以降に導入されました。主な目的は、定数のセットを編成することです。それ以前は、定数のセットは通常、定数を定義する方法で表されていました。
public static final int RED = 1;
public static final int BLACK = 2;
public static final int GREEN = 3;
ただし、定数の例には悪い点があります。たとえば、数値が1である場合でも、REDと誤解される可能性があります。これで、列挙型を直接使用して整理できるようになり、型、列挙型が作成されます。通常の成形の代わりに1。
public enum TestEnum {
RED,BLACK,GREEN;
}
利点:統一された管理
シナリオの定数を整理します:エラーステータスコード、メッセージタイプ、色分割、ステートマシンなど...
本質:これはjava.lang.Enum
、のサブクラスです。つまり、明示的な継承がない場合でも、Enum
デフォルトでこのクラスを継承する、自分で作成した列挙型クラスです。
2.列挙型の使用
2.1switchステートメント
public enum TestEnum {
RED,BLACK,GREEN,PINK;
public static void main(String[] args) {
TestEnum testEnum = TestEnum.BLACK;
switch (testEnum) {
case RED:
System.out.println("red!");
break;
case BLACK:
System.out.println("black!");
break;
case GREEN:
System.out.println("green!");
break;
case PINK:
System.out.println("pink!");
break;
default:
break;
}
}
}
2.2一般的に使用される方法
Enum
クラスの一般的なメソッド
メソッド名 | 説明 |
---|---|
values() | 列挙型のすべてのメンバーを配列として返します |
ordinal() | 列挙型メンバーのインデックス位置を取得します |
valueOf() | 通常の文字列を列挙型インスタンスに変換します |
compareTo() | 2つの列挙型メンバーが定義されている順序を比較します |
2.2.1values()の使用
public enum TestEnum {
RED,BLACK,GREEN,PINK;
public static void main(String[] args) {
TestEnum[] testEnums = TestEnum.values();
for (int i = 0; i < testEnums.length; i++) {
System.out.println(testEnums[i]);
}
}
}
2.2.2 ordinal()の使用
public enum TestEnum {
RED,BLACK,GREEN,PINK;
public static void main(String[] args) {
TestEnum[] testEnums = TestEnum.values();
for (int i = 0; i < testEnums.length; i++) {
System.out.println(testEnums[i].ordinal());
}
}
}
2.2.3 valueOf()の使用
public enum TestEnum {
RED,BLACK,GREEN,PINK;
public static void main(String[] args) {
System.out.println(TestEnum.valueOf("RED"));
System.out.println(TestEnum.valueOf("BLACK"));
System.out.println(TestEnum.valueOf("WHITE"));
}
}
2.2.4 compareTo()の使用
public enum TestEnum {
RED,BLACK,GREEN,PINK;
public static void main(String[] args) {
TestEnum testEnum1 = TestEnum.RED;
TestEnum testEnum2 = TestEnum.BLACK;
System.out.println(testEnum1.compareTo(testEnum2));
System.out.println(RED.compareTo(GREEN));
System.out.println(PINK.compareTo(RED));
}
}
2.2.5コンストラクタ
public enum TestEnum {
RED("red",1),BLACK("black",11),GREEN("green",111),PINK("pink",1111);
private String name;
private int ordinal;
private TestEnum(String name,int ordinal){
this.name = name;
this.ordinal = ordinal;
}
public static TestEnum getEnumKey (int ordinal) {
for (TestEnum t :TestEnum.values()){
if(t.ordinal == ordinal){
return t;
}
}
return null;
}
public static void main(String[] args) {
System.out.println(getEnumKey(1111));
}
}
2.3注意事項
- 自分で作成した列挙型クラスは、デフォルトで継承されます
Enum
。 - 独自の列挙型クラスのコンストラクターはデフォルトでプライベート
- 値メソッドを含まないカスタム列挙型を作成し、Javaファイルをコンパイルすると、Javaコンパイラが自動的にこのメソッドの生成を支援します。
3.列挙の長所と短所
アドバンテージ:
- 列挙型定数はより単純で安全です。
- 列挙型には、より洗練されたコードのための組み込みメソッドがあります
欠点:
- 継承不可、拡張不可
4.列挙と反映
リフレクションで見たところ、コンストラクターがプライベートであっても、リフレクションを介してインスタンスオブジェクトを取得でき、列挙型のコンストラクターもプライベートであることがわかりました。取得できますか?次に、実験してみましょう。
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Reflect {
public static void reflectPrivateConstructor() {
try {
Class<?> c = Class.forName("TestEnum");
Constructor<?> constructor = c.getDeclaredConstructor(String.class,int.class);
constructor.setAccessible(true);
TestEnum testEnum = (TestEnum) constructor.newInstance("1231123",123123);
System.out.println(testEnum);
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
reflectPrivateConstructor();
}
}
実行後にエラーが報告されます。
ここでの意味は、対応する構築メソッドがないことです。
なぜこれが発生するのですか?
デフォルトの継承java.lang.Enum
は、コンストラクターを除く親クラスからすべてを継承し、サブクラスは親クラスの構築を支援する必要があるためです。私たちが作成したクラスは、親クラスの構築に役立ちませんでした。列挙は特別です。2つ作成しましたが、デフォルトで2つのパラメーターも追加しました。
つまり、独自のコンストラクターには2つのパラメーターがあり、1つはStringで、もう1つはint。同時に、デフォルトで2つのパラメーターが背後にあります。1つはStringで、もう1つはintです。つまり、ここでは4つのパラメーターを正しく指定しています。
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Reflect {
public static void reflectPrivateConstructor() {
try {
Class<?> c = Class.forName("TestEnum");
Constructor<?> constructor = c.getDeclaredConstructor(String.class,int.class,String.class,int.class);
constructor.setAccessible(true);
TestEnum testEnum = (TestEnum) constructor.newInstance("1231123",123123,"4444",2323);
System.out.println(testEnum);
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
reflectPrivateConstructor();
}
}
実行後、
この時点での異常情報は、それが私の方法の1つであることを示しています。この方法は次のとおりです。newInstance()
エラーが報告されます。
ソースコードを表示します。
4.1まとめ
リフレクションは強力ですが、列挙クラスのインスタンスはリフレクションでは取得できません。