列挙型コンストラクターは、プライベートまたはパッケージのデフォルトである必要があり、保護またはパブリックアクセス修飾子は許可されていません。なぜそうなのか
4 に答える
列挙型には、定義上、列挙型自体で宣言および構築されるインスタンスの固定セットがあるためです。したがって、列挙型クラス自体の外部からコンストラクターを使用することは意味がありません。
そして、列挙型コンストラクターであるAFAIKは、常に明示的または暗黙的にプライベートです。
Javaチュートリアルから:
列挙型のコンストラクターは、パッケージプライベートまたはプライベートアクセスである必要があります。列挙型本体の先頭で定義されている定数を自動的に作成します。列挙型コンストラクターを自分で呼び出すことはできません。
列挙型の新しいインスタンスを作成できることは意味がないため、言語によって作成できなくなります。
列挙型は(あなたが)インスタンス化することを意図したものではありません。
http://docs.oracle.com/javase/tutorial/reflect/special/enumTrouble.html:
ヒント:定義された列挙型定数が一意になるのを妨げるため、列挙型を明示的にインスタンス化しようとするとコンパイル時エラーになります。この制限は、リフレクティブコードでも適用されます。デフォルトのコンストラクターを使用してクラスをインスタンス化しようとするコードは、最初にClass.isEnum()を呼び出して、クラスが列挙型であるかどうかを判別する必要があります。
列挙型を動的に拡張できない理由は、インスタンス化された値がClassオブジェクトのバイトコードにコンパイルされるためです。
public T[] getEnumConstants()
Returns the elements of this enum class or null if this Class object does not
represent an enum type.
その結果、クラスオブジェクトは変更できないため、新しいインスタンスを作成しようとしても、実際のクラスに渡すことはできません。この動作が必要な場合は、自分でシミュレートし、それぞれを表すために何らかの一意の値を指定してから、通常のカウンターを作成し、最後にすべての値を保持する静的マップ(またはその他の構造)を作成する必要があります。 。
public class MyEnum {
private static AtomicInteger nextOrdinal = new AtomicInteger(0);
private static Map<Integer, MyEnum> instances =
new HashMap<Integer, MyEnum>();
private int ordinal;
private String name;
public MyEnum(String name) {
super();
this.ordinal = nextOrdinal.incrementAndGet();
this.name = name;
instances.put(Integer.valueOf(this.ordinal), this);
}
public String name() {
return name;
}
public int ordinal() {
return ordinal;
}
public static Set<MyEnum> getEnumConstants() {
return Collections.unmodifiableSet(instances.values());
}
public static MyEnum fromInt(int ordinal) {
return instances.get(Integer.valueOf(ordinal));
}
public static MyEnum fromString(String name) {
for (MyEnum val : instances.values()) {
if (val.name().equals(name)) {
return val;
}
}
return null;
}
}
おそらく、.equalsメソッドと.hashcodeメソッドが必要になるだけでなく、同じ名前が複数回使用されないようにする必要があります(コンストラクターで実行して、名前が重複している場合はIllegalStateExceptionなどをスローできます)。