come from http://www.it165.net/pro/html/201305/5643.html
-
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 的类。
01.Compiled from"EnumClass.java"02.finalclassenumerated.Shrubberyextendsjava.lang.Enum{03.publicstaticfinalenumerated.Shrubbery GROUND;04.publicstaticfinalenumerated.Shrubbery CRAWLING;05.publicstaticfinalenumerated.Shrubbery HANGING;06.static{};07.publicstaticenumerated.Shrubbery[] values();08.publicstaticenumerated.Shrubbery valueOf(java.lang.String);09.}由于擦除的原因, enum Shrubbery {} 实事上等价于 final class Shrubbery extends Enum<Shrubbery>(即告诉编译器Shrubbery 继承于 Enum,而这个Enum 的泛型参数就是 Shrubbery 自身)。现在我们检查下,Shrubbery 符不符合 <E extends Enum<E>> 形式,如果你还看不明白,可以把 E 替换成Shrubbery ,你可以看到这就是 Shrubbery 的类定义,所以Shrubbery 完全符合要求!另外编译加上 final 修饰的原因是不希望 Enum 的子类可以作为父类被其它类继承。
01.//: enumerated/EnumClass.java02.// Capabilities of the Enum class03.packageenumerated;04.importstaticnet.mindview.util.Print.*;05.06.enumShrubbery { GROUND, CRAWLING, HANGING }07.08.// 错误无法继承09.//enum ShrubberySub extends Shrubbery {};10.enumAnotherShrubbery{GROUND, CRAWLING, HANGING }11.12.publicclassEnumClass {13.publicstaticvoidmain(String[] args) {14.for(Shrubbery s : Shrubbery.values()) {15.print(s +" ordinal: "+ s.ordinal());16.printnb(s.compareTo(Shrubbery.CRAWLING) +" ");17.printnb(s.equals(Shrubbery.CRAWLING) +" ");18.print(s == Shrubbery.CRAWLING);19.print(s.getDeclaringClass());20.print(s.name());21.print("----------------------");22.}23.// Produce an enum value from a string name:24.for(String s :"HANGING CRAWLING GROUND".split(" ")) {25.Shrubbery shrub = Enum.valueOf(Shrubbery.class, s);26.print(shrub);27.}28.29.// 编译不过,在不同 enum 类型中进行比较30.Shrubbery.GROUND.compareTo(AnotherShrubbery.GROUND);31.}32.}为了验证上面的推出的结果,我写了下面手机类来进行测试。同类手机可以进行系统版本号的比较,不同类的手机系统版本号比较没有意义。通过 E extends Handphone<E> 的泛型限定,我们就可以阻止编译器在 Iphone 和 Android 手机之间进行系统版本号的比较。 www.it165.net
01.//: generics/WeirdGenerics.java02.// 怪异的泛型03.packagegenerics;04.05.abstractclassHandphone<EextendsHandphone<E>>implementsComparable<E>{06.publicabstractintosVersion();07.publicintcompareTo(E o){08.returnosVersion() - o.osVersion();09.}10.}11.12.classIphoneextendsHandphone<Iphone>{13.privateintversion;14.publicIphone(intversion){15.this.version = version;16.}17.publicintosVersion(){18.returnversion;19.}20.}21.22.class<a href="http://www.it165.net/pro/ydad/"target="_blank"class="keylink">Android</a>extendsHandphone<Android>{23.privateintversion;24.publicAndroid(intversion){25.this.version = version;26.}27.publicintosVersion(){28.returnversion;29.}30.}31.32.publicclassWeirdGenerics{33.publicstaticvoidmain(String []args){34.Iphone i4 =newIphone(4), i5 =newIphone(5);35.Android a2 =newAndroid(2), a3 =newAndroid(3);36.37.System.out.println(i5.compareTo(i4));38.System.out.println(a3.compareTo(a2));39.// 错误,两种手机之间不能比较系统版本大小40.//System.out.println(i5.compareTo(a3));41.}42.}
浙公网安备 33010602011771号