对扩展现有枚举类型的泛型感到困惑

sta*_*ror 3 java generics enums interface type-erasure

问题 1:我对这些代码有点困惑:

public class MyClass1 <E extends Enum<?>> {
    // ...
}
public class MyClass2 <E extends Enum<E>> {
    // ... 
}
Run Code Online (Sandbox Code Playgroud)

MyClass1和之间有什么不同MyClass2,这三个不同E意味着什么?

问题 2:从Class Enum <E extends Enum<E>>

这是所有Java语言枚举类型的公共基类。

但不是所有Enum类型的共同基类吗Enum<E>?

问题 3:现在我有这门课:

public class MyClass<E extends Enum<E>> {

    // for example, EnumSet<Category> 
    public Set<E> category; 

    // how to initial this member
    private Class<E> enumType; 

    // initial this.category with given strings
    public void getEnumSetFromStringList(List<String> list) {
        this.category = EnumSet.noneOf(enumType);
        for (String str : list) {
            this.category.add(Enum.valueOf(this.enumType, str));
        }
    }
}

// this is the Category of Enum type
public enum Category {

    LOCATION("LOCATION"), 
    HUMAN("HUMAN"),
    // ...
    DESCRIPTION("DESCRIPTION");

    private final String categoryName;

    Category(String categoryName) {
        this.categoryName= categoryName;
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 我如何enumType在 中初始化数据字段MyClass?

  2. 如果MyClass不包含数据字段enumType,函数如何getEnumSetFromStringList(List<String> list)获取泛型类型的类型<E extends Enum<?>>?

  3. 我可以通过这种方式获取 Enum 类型吗:E.class?如果不是,是否是由于编译期间泛型类型的类型擦除所致?

Pau*_*ton 5

Enum<E extends Enum<E>>很难理解。

让我们考虑两个enums。

enum Colour { RED, GREEN, BLUE }

enum Shape { SQUARE, CIRCLE, TRIANGLE }

想想compareTo()中的方法Enum。这用于Enum根据声明的顺序比较相同的不同常量。如果Enum不是泛型类,则此方法的签名必须是int compareTo(Enum e)。但这没有任何意义,因为这样你就可以将 aColour与 a进行比较Shape。compareTo我们希望in的签名Colour为int compareTo(Colour colour)。唯一的方法是 ifEnum是一个带有类型参数的泛型类E,并且其类型参数Colour是Colour!只要Colouris的类型参数和isColour的类型参数,那么我们就只能比较s 与s 以及s 与s。ShapeShapeColourColourShapeShape

因此,在 的定义中Enum,我们需要某种方式来表达,对于每个子类,类型参数不仅必须是 an enum,而且类型参数应该是子类本身。因此E不应该只是延伸Enum而是E应该延伸Enum<E>!

这就是从何Enum<E extends Enum<E>>而来。

(你不应该写Enum<E extends Enum<?>>)。

赋值的一种方法enumType是将 a 传递Class<E>给构造函数。像这样

class MyClass2<E extends Enum<E>> {
    private final Class<E> enumType;

    MyClass2(Class<E> enumType) {
        this.enumType = enumType;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您不想这样做,Class<E>在运行时获取对象的另一种方法是使用Enum实​​例方法getDeclaringClass()。不过,这需要您手头有一个实例E来调用该方法。在运行时获取所有枚举常量的数组的一种方法是编写e.getDeclaringClass().getEnumConstants().

您无法编写E.class,因为正如您所说,泛型是使用类型擦除过程实现的。在运行时, anArrayList<String>只是一个ArrayList,因此无法访问类型参数。