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.}
