Java列挙型は素晴らしいです。ジェネリックもそうです。もちろん、型消去のために後者の限界を知っています。しかし、理解できないことが1つあります。なぜ、このような列挙型を作成できないのですか。
public enum MyEnum<T> {
LITERAL1<String>,
LITERAL2<Integer>,
LITERAL3<Object>;
}
このジェネリック型パラメーター<T>
は、さまざまな場所で役立ちます。メソッドへのジェネリック型パラメーターを想像してください:
public <T> T getValue(MyEnum<T> param);
または列挙クラス自体でも:
public T convert(Object o);
より具体的な例#1
上記の例は一部にとって抽象的すぎるように見えるかもしれないので、これを行う理由のより現実的な例を次に示します。この例では、使用したい
- 列挙型。プロパティキーの有限セットを列挙できるため
- ジェネリックス。これは、プロパティレベルを格納するためのメソッドレベルの型安全性を持つことができる
public interface MyProperties {
public <T> void put(MyEnum<T> key, T value);
public <T> T get(MyEnum<T> key);
}
より具体的な例#2
データ型の列挙があります:
public interface DataType<T> {}
public enum SQLDataType<T> implements DataType<T> {
TINYINT<Byte>,
SMALLINT<Short>,
INT<Integer>,
BIGINT<Long>,
CLOB<String>,
VARCHAR<String>,
...
}
各列挙リテラルには、明らかにジェネリック型に基づいた追加のプロパティがあります <T>
、同時に列挙型(不変、シングルトン、列挙可能など)になります。
質問:
誰もこれを考えなかったのですか?これはコンパイラ関連の制限ですか?キーワード「enum」が構文シュガーとして実装され、JVMに対して生成されたコードを表すという事実を考えると、この制限は理解できません。
誰が私にこれを説明できますか?答える前に、これを考慮してください:
- 私はジェネリック型が消去されていることを知っています:-)
- Classオブジェクトを使用する回避策があることを知っています。それらは回避策です。
- ジェネリック型は、該当する場合(たとえば、convert()メソッドを呼び出すとき)にコンパイラー生成の型キャストになります。
- ジェネリック型<T>は列挙型にあります。したがって、列挙型の各リテラルによってバインドされます。したがって、コンパイラーは、次のようなものを作成するときに適用するタイプを知っています。
String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject);
T getvalue()
メソッドのジェネリック型パラメーターにも同じことが当てはまります。コンパイラは、呼び出し時に型キャストを適用できますString string = someClass.getValue(LITERAL1)
enum
。Java1.5より前に使用していた「型保証された列挙型」のイディオムに変換します。突然、列挙型メンバーをパラメーター化できます。それがおそらく私がやろうとしていることです。