一尘不染

为什么Java枚举文字不能具有通用类型参数?

java

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()方法时)导致编译器生成的类型转换
  • 通用类型将在枚举上。因此,它受每个枚举文字的约束。因此,编译器会知道在编写类似内容时应应用哪种类型String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject);
  • T getvalue()方法中的泛型类型参数也是如此。编译器可以在调用时应用类型转换String string = someClass.getValue(LITERAL1)

阅读 259

收藏
2020-09-09

共1个答案

一尘不染

现在正在从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

不幸的是,JEP仍在努力解决重大问题:http : //mail.openjdk.java.net/pipermail/amber-spec-
experts/2017-May/000041.html

2020-09-09