Luk*_*der 139 java generics enums
Java枚举很棒.仿制药也是如此.当然,由于类型擦除,我们都知道后者的局限性.但有一点我不明白,为什么我不能创建这样的枚举:
public enum MyEnum<T> {
LITERAL1<String>,
LITERAL2<Integer>,
LITERAL3<Object>;
}
Run Code Online (Sandbox Code Playgroud)
这个泛型类型参数<T>
反过来可以在各个地方使用.想象一下方法的泛型类型参数:
public <T> T getValue(MyEnum<T> param);
Run Code Online (Sandbox Code Playgroud)
甚至在枚举类中:
public T convert(Object o);
Run Code Online (Sandbox Code Playgroud)
由于上面的例子对某些人来说可能看起来过于抽象,所以这里有一个更真实的例子,说明我为什么要这样做.在这个例子中我想使用
public interface MyProperties {
public <T> void put(MyEnum<T> key, T value);
public <T> T get(MyEnum<T> key);
}
Run Code Online (Sandbox Code Playgroud)
我有一个数据类型的枚举:
public interface DataType<T> {}
public enum SQLDataType<T> implements DataType<T> {
TINYINT<Byte>,
SMALLINT<Short>,
INT<Integer>,
BIGINT<Long>,
CLOB<String>,
VARCHAR<String>,
...
}
Run Code Online (Sandbox Code Playgroud)
每个枚举文字显然都有基于泛型类型的附加属性<T>
,同时又是枚举(不可变,单例,可枚举等).
没有人想到这个吗?这是与编译器相关的限制吗?考虑到事实,关键字" 枚举 "是作为语法糖实现的,表示生成的代码到JVM,我不明白这个限制.
谁能向我解释一下?在你回答之前,考虑一下:
String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject);
T getvalue()
.编译器可以在调用时应用类型转换String string = someClass.getValue(LITERAL1)
Luk*_*der 48
现在正在讨论JEP-301增强型枚举.JEP中给出的例子正是我所寻找的:
enum Argument<X> { // declares generic enum
STRING<String>(String.class),
INTEGER<Integer>(Integer.class), ... ;
Class<X> clazz;
Argument(Class<X> clazz) { this.clazz = clazz; }
Class<X> getClazz() { return clazz; }
}
Class<String> cs = Argument.STRING.getClazz(); //uses sharper typing of enum constant
Run Code Online (Sandbox Code Playgroud)
不幸的是,JEP仍在努力应对重大问题:http://mail.openjdk.java.net/pipermail/amber-spec-experts/2017-May/000041.html
Mar*_*ten 11
答案在于问题:
因为类型擦除
这两种方法都不可能,因为参数类型被删除.
public <T> T getValue(MyEnum<T> param);
public T convert(Object);
Run Code Online (Sandbox Code Playgroud)
要实现这些方法,您可以构建枚举为:
public enum MyEnum {
LITERAL1(String.class),
LITERAL2(Integer.class),
LITERAL3(Object.class);
private Class<?> clazz;
private MyEnum(Class<?> clazz) {
this.clazz = clazz;
}
...
}
Run Code Online (Sandbox Code Playgroud)
因为你不能。说真的 可以将其添加到语言规范中。还没有。这会增加一些复杂性。成本节约意味着它不是一个高度优先事项。
更新:当前已添加到JEP 301:增强枚举下的语言中。
ENUM 中还有其他方法不起作用。会返回什么MyEnum.values()
?
关于什么MyEnum.valueOf(String name)
?
对于 valueOf 如果您认为编译器可以创建像这样的泛型方法
公共静态MyEnum valueOf(字符串名称);
为了像这样称呼它MyEnum<String> myStringEnum = MyEnum.value("some string property")
,那也行不通。例如,如果您打电话怎么办MyEnum<Int> myIntEnum = MyEnum.<Int>value("some string property")
?不可能实现该方法正确工作,例如,当您调用它时,MyEnum.<Int>value("some double property")
由于类型擦除而抛出异常或返回 null。