作者:wenyinfeng
转载时,请注明原文出处,谢谢!
public abstract class Enum<E extends Enum<E>>
extends Object
implements Comparable<E>, Serializable
为什么 Enum 类需要使用如下这么奇怪的泛型,<E extends Enum<E>>,初次看真是让我晕了, E 到底代表什么啊?为什么不定义成 public abstract class Enum extends Object 呢?很容易找到答案,Enum 需要实现Comparable 比较接口。
那似乎也可以定义成 public abstract class Enum<E>extends Object implements Comparable<E>, Serializable 。仔细想,就会发现会有问题,Comparable 的compareTo()方法是这样的: public final int compareTo(E o),我们肯定不希望这个 E 是任何类型的,而是希望这个E 是 Enum 类型的,同时我们不希望两个不同的 Enum 子类实例可以进行比较(没有意义),即我们最希望的是同一个 Enum 子类的实例进行比较。
下面 的 EnumClass.java 摘自 《Thinking in java 》第19章枚举类型,稍微修改了下。通过 javap javap Shrubbery 反编译,可以看到 Shrubbery 是一个继承自 Enum 的类。
Compiled from "EnumClass.java"
final class enumerated.Shrubbery extends java.lang.Enum{
}
由于擦除的原因, enum Shrubbery {} 实事上等价于 final class Shrubbery extends Enum<Shrubbery>(即告诉编译器Shrubbery 继承于 Enum,而这个Enum 的泛型参数就是 Shrubbery 自身)。现在我们检查下,Shrubbery 符不符合 <E extends Enum<E>> 形式,如果你还看不明白,可以把 E 替换成Shrubbery ,你可以看到这就是 Shrubbery 的类定义,所以Shrubbery 完全符合要求!另外编译加上 final 修饰的原因是不希望 Enum 的子类可以作为父类被其它类继承。
//: enumerated/EnumClass.java
// Capabilities of the Enum class
package enumerated;
import static net.mindview.util.Print.*;
enum Shrubbery { GROUND, CRAWLING, HANGING }
// 错误无法继承
//enum ShrubberySub extends Shrubbery {};
enum AnotherShrubbery{GROUND, CRAWLING, HANGING }
public class EnumClass {
}
为了验证上面的推出的结果,我写了下面手机类来进行测试。同类手机可以进行系统版本号的比较,不同类的手机系统版本号比较没有意义。通过 E extends Handphone<E> 的泛型限定,我们就可以阻止编译器在 Iphone 和 Android 手机之间进行系统版本号的比较。
//: generics/WeirdGenerics.java
// 怪异的泛型
package generics;
abstract class Handphone<E extends Handphone<E>> implements Comparable<E>{
}
class Iphone extends Handphone<Iphone>{
}
class Android extends Handphone<Android>{
}
public class WeirdGenerics{
}
作者:wenyinfeng
转载时,请注明原文出处, 谢谢!
















