Java枚举非常好用。泛型也很棒。当然,我们都知道后者因为类型擦除而存在一定的限制。但是有一件事情我不明白,为什么我不能创建这样的枚举:
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的表示,我不理解这个限制。
谁能向我解释一下?在回答之前,请考虑以下几点:
- 我知道泛型类型被擦除了 :-)
- 我知道使用类对象有解决方法。但它们只是解决方法。
- 泛型类型会导致编译器在适用时生成类型转换(例如,在调用convert()方法时)
- 泛型类型<T>将出现在枚举中。因此,每个枚举的字面量都将受到其约束。因此,当编写诸如
String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject);
之类的语句时,编译器将知道应用哪种类型。 - 对于
T getvalue()
方法中的泛型类型参数也是同样的情况。当调用String string = someClass.getValue(LITERAL1)
时,编译器可以应用类型转换。
enum
转换成我们在 Java 1.5 之前使用的 "类型安全枚举" 惯用法。这样一来,你就可以将枚举成员参数化了。我现在可能会这么做。 - Marko Topolnik