乐趣区

Java泛型 – 如何破解Enum>?

以下内容翻译自链接内容其中一段章节:
How do I decrypt “Enum<E extends Enum<E>>”?
public abstract class Enum<E extends Enum<E>> {

}
Enum 类是 Java 内所有枚举类型的通用基础类。例如 enum Color {} 会被编译成 class Color extends Enum<Color>。Enum 基类存在的目的是为这些所有枚举类型提供基础的方法及功能。
以下是 Euum 类的骨架:
public abstract class Enum< E extends Enum<E>> implements Comparable<E>, Serializable {
private final String name;
public final String name() { …}
private final int ordinal;
public final int ordinal() { …}

protected Enum(String name, int ordinal) {…}

public String toString() { …}
public final boolean equals(Object other) {…}
public final int hashCode() { …}
protected final Object clone() throws CloneNotSupportedException { …}
public final int compareTo(E o) {…}

public final Class<E> getDeclaringClass() { …}
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {…}
}
以下是实际使用中的 enum Color:
enum Color {RED, BLUE, GREEN}
Java 编译器会将它编译成:
public final class Color extends Enum<Color> {
public static final Color[] values() {return (Color[])$VALUES.clone();}
public static Color valueOf(String name) {…}
private Color(String s, int i) {super(s, i); }

public static final Color RED;
public static final Color BLUE;
public static final Color GREEN;

private static final Color $VALUES[];

static {
RED = new Color(“RED”, 0);
BLUE = new Color(“BLUE”, 1);
GREEN = new Color(“GREEN”, 2);
$VALUES = (new Color[] {RED, BLUE, GREEN});
}
}
Color 类继承了所有 Enum<Color> 所实现了的方法。compareTo 方法就是其中之一。如果加上类的限制,那么 Color.compareTo 应该接收的参数是 Color 类型实例。为了让这能够实现,Enum 设置了泛型 <E> 并在 Enum.compareTo 实现中接收 E 类型的实例作为方法参数。

而作为继承的结果,Color 类型从 Enum<Color> 中派生出来的 compareTo 方法实际上接收的参数就是 Color 类型的实例,这完美地达成了设计目标。
如果我们继续深入解剖类声明 Enum<E extends Enum<E>>,我们可以看到它有以下几方面的意义:
第一,Enum 的泛型 E 的上界为 Enum 自身。这确保了只有 Enum 的子类才被允许成为泛型参数。(理论上,Enum 可以被它自己具现化,例如 Enum<Enum>,但这没有意义,并且很难想象这会有对应的应用场景。)
第二,泛型 E 的上界被进一步限定为 extends Enum<E>,这确保了 Enum< 子类 A > 和 Enum< 子类 A > 的子类 A 的继承关系一定满足子类 A extends Enum< 子类 A >。类似子类 A extends Enum< 子类 B > 这样的声明是会被编译器拒绝的,因为这个声明并不匹配泛型参数的上界。
第三,基于 Enum 被设计为泛型,这意味着 Enum 类中的某些方法的方法参数及返回类型在运行时是未知类型(又或者说是依赖于某未知类型)。而根据 E extends Enum<E>,我们可以知道 E 肯定会是 Enum<?> 的子类。所以,在具象化类型 Enum< 某具体类 > 中,这些泛型方法的参数及返回类型就会被编译器转换为某具体类型。(compareTo 就是一个例子)。总结来说,E extends Enum<E> 保证了每个 Enum<E> 的子类中都能够接收并返回该子类类型。

退出移动版