首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么Java enum文本不能具有泛型类型参数?

为什么Java enum文本不能具有泛型类型参数?
EN

Stack Overflow用户
提问于 2010-11-27 17:12:05
回答 8查看 31.2K关注 0票数 162

Java枚举非常棒。泛型也是如此。当然,由于类型擦除,我们都知道后者的局限性。但有一件事我不明白,为什么我不能创建这样的枚举:

代码语言:javascript
运行
复制
public enum MyEnum<T> {
    LITERAL1<String>,
    LITERAL2<Integer>,
    LITERAL3<Object>;
}

这样,这个泛型类型参数<T>就可以在不同的地方发挥作用。想象一下一个方法的泛型类型参数:

代码语言:javascript
运行
复制
public <T> T getValue(MyEnum<T> param);

或者甚至在枚举类本身中:

代码语言:javascript
运行
复制
public T convert(Object o);

更具体的例子#1

由于上面的例子对一些人来说可能太抽象了,所以这里有一个更真实的例子来说明我为什么要这样做。在本例中,我想使用

  • 枚举,因为这样我就可以枚举
  • 泛型的属性键的有限集合,因为这样我就可以拥有用于存储属性的方法级类型安全

代码语言:javascript
运行
复制
public interface MyProperties {
     public <T> void put(MyEnum<T> key, T value);
     public <T> T get(MyEnum<T> key);
}

更具体的例子#2

我有一个数据类型的枚举:

代码语言:javascript
运行
复制
public interface DataType<T> {}

public enum SQLDataType<T> implements DataType<T> {
    TINYINT<Byte>,
    SMALLINT<Short>,
    INT<Integer>,
    BIGINT<Long>,
    CLOB<String>,
    VARCHAR<String>,
    ...
}

很明显,每个枚举文本都具有基于泛型类型<T>的附加属性,同时又是一个枚举(不可变、单例、可枚举等)。

问题:

没人想到这一点吗?这是与编译器相关的限制吗?考虑到关键字“JVM ”被实现为语法糖,向表示生成的代码,我不理解这个限制。

谁能给我解释一下?在回答之前,请考虑以下内容:

  • 我知道泛型类型被删除了:-)
  • 我知道有一些使用类对象的变通方法。它们是转换类型,只要适用就会导致编译器生成的类型转换(例如,当调用workarounds.
  • Generic ()方法
  • 时,泛型类型将在枚举上。因此,它由枚举的每个文字绑定。因此,在编写类似String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject);
  • The的代码时,编译器应该知道要应用哪种类型,这同样适用于T getvalue()方法中的泛型类型参数。编译器可以在调用String string = someClass.getValue(LITERAL1)

时应用类型转换

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2016-12-08 03:04:05

这已经在JEP-301 Enhanced Enums讨论过了,遗憾的是它被撤回了。JEP中给出的示例是,这正是我正在寻找的:

代码语言:javascript
运行
复制
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

不幸的是,JEP正在与无法解决的重大问题作斗争:http://mail.openjdk.java.net/pipermail/amber-spec-experts/2017-May/000041.html

票数 61
EN

Stack Overflow用户

发布于 2010-11-27 17:27:05

答案就在问题中:

类型擦除导致的

这两种方法都不可行,因为参数类型已被擦除。

代码语言:javascript
运行
复制
public <T> T getValue(MyEnum<T> param);
public T convert(Object);

但是,要实现这些方法,您可以将枚举构造为:

代码语言:javascript
运行
复制
public enum MyEnum {
    LITERAL1(String.class),
    LITERAL2(Integer.class),
    LITERAL3(Object.class);

    private Class<?> clazz;

    private MyEnum(Class<?> clazz) {
      this.clazz = clazz;
    }

    ...

}
票数 12
EN

Stack Overflow用户

发布于 2011-02-25 02:21:46

因为你不能。说真的。这可以添加到语言规范中。不是这样的。这会增加一些复杂性。这对成本的好处意味着它不是一个高优先级。

更新:目前正在添加到JEP 301: Enhanced Enums下的语言中。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4290878

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档