Enum <E extends Enum<E>>

在枚举类的源代码中,有这样的定义:
Enum <E extends Enum<E>>

在网上看了很多人的文章都没有看懂,请能够解释清楚的大神帮忙说说。


As a type that can only be instantiation for its subtypes, and those subtypes will inherit some useful methods, some of which take subtype arguments (or otherwise depend on the subtype).
The context in which " Enum<E extends Enum<E>> " appears is the declaration of the Enum class in package java.lang :
public abstract class Enum<E extends Enum<E>> {
...
}
The type Enum is the common base class of all enumeration types. In Java an enumeration type such as Color is translated into a class Color that extends Enum<Color> . The purpose of the superclass Enum is to provide functionality that is common to all enumeration types.
Here is a sketch of class Enum :

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) { ... }
}
The surprising feature in the declaration " Enum<E extends Enum<E>> " is the fact that the newly defined class Enum and its newly defined type parameter E appear in the bound of that same type parameter. It means that the Enum type must be instantiated for one of its subtypes. In order to understand why this makes sense, consider that every enum type is translated into a subtype of Enum .
Here is the contrived enum type Color :

enum Color {RED, BLUE, GREEN}
The compiler translates it into the following class:
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 });
}
}
The inheritance has the effect that the Color type inherits all the methods implemented in Enum<Color> . Among them is the compareTo method. The Color.compareTo method should probably take a Color as an argument. In order to make this happen class Enum is generic and the Enum.compareTo method takes Enum 's type parameter E as an argument. As a result, type Color derived from Enum<Color> inherits a compareTo method that takes a Color as and argument, exactly as it should.

If we dissect the declaration " Enum<E extends Enum<E>> " we can see that this pattern has several aspects.

First, there is the fact that the type parameter bound is the type itself: " Enum <E extends Enum <E>> ". It makes sure that only subtypes of type Enum are permitted as type arguments. (Theoretically, type Enum could be instantiated on itself, like in Enum<Enum> , but this is certainly not intended and it is hard to imagine a situation in which such an instantiation would be useful.)

Second, there is the fact that the type parameter bound is the parameterized type Enum <E> , which uses the type parameter E as the type argument of the bound. This declaration makes sure that the inheritance relationship between a subtype and an instantiation of Enum is of the form " X extends Enum<X> ". A subtype such as " X extends Enum<Y> " cannot be declared because the type argument Y would not be within bounds; only subtypes of Enum<X> are within bounds.

Third, there is the fact that Enum is generic in the first place. It means that some of the methods of class Enum take an argument or return a value of an unknown type (or otherwise depend on an unknown type). As we already know, this unknown type will later be a subtype X of Enum<X> . Hence, in the parameterized type Enum<X> , these methods involve the subtype X , and they are inherited into the subtype X . The compareTo method is an example of such a method; it is inherited from the superclass into each subclass and has a subclass specific signature in each case.

To sum it up, the declaration " Enum<E extends Enum<E>> " can be decyphered as: Enum is a generic type that can only be instantiated for its subtypes, and those subtypes will inherit some useful methods, some of which take subtype specific arguments (or otherwise depend on the subtype).

Java泛型 - 如何破解"Enum<E extends Enum<E>>"?

以下内容翻译自链接内容其中一段章节:

  • How do I decrypt "Enum<E extends Enum<E>>"?
Enum<E>仅允许它的子类Color extends Enum<Color>去具现化它,并且Color继承了Enum<Color>中一些有用的方法,而这些方法是接收或返回Color类型的参数的。

public abstract class Enum<E extends Enum<E>> {
    ...
}

Enum类是Java内所有枚举类型的通用基础类。例如enum Color {}会被编译成class Color extends Enum<Color>Enum<E>泛型基类存在的目的是为所有枚举类型提供基础的方法及功能。

以下是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类型的实例作为方法参数。

clipboard.png

作为继承的结果,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>的子类中都能够接收并返回该子类类型E

 
本文系翻译,阅读原文
http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ106

=========================

工作机会(内部推荐):发送邮件至gaoyabing@126.com,看到会帮转内部HR。

邮件标题:X姓名X_X公司X_简历(如:张三_东方财富_简历),否则一律垃圾邮件!

公司信息:

  1. 1.东方财富|上海徐汇、南京|微信客户端查看职位(可自助提交信息,微信打开);
原文地址:https://www.cnblogs.com/Chary/p/14923972.html