Enum 奇怪的泛型 自限定泛型 循环泛型


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. final class enumerated.Shrubbery extends java.lang.Enum{
    03. public static final enumerated.Shrubbery GROUND;
    04. public static final enumerated.Shrubbery CRAWLING;
    05. public static final enumerated.Shrubbery HANGING;
    06. static {};
    07. public static enumerated.Shrubbery[] values();
    08. public static enumerated.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.java
    02. // Capabilities of the Enum class
    03. package enumerated;
    04. import static net.mindview.util.Print.*;
    05.  
    06. enum Shrubbery { GROUND, CRAWLING, HANGING }
    07.  
    08. // 错误无法继承
    09. //enum ShrubberySub extends Shrubbery {};
    10. enum AnotherShrubbery{GROUND, CRAWLING, HANGING }
    11.  
    12. public class EnumClass {
    13. public static void main(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.java
    02. // 怪异的泛型
    03. package generics;
    04.  
    05. abstract class Handphone<E extends Handphone<E>> implements Comparable<E>{
    06. public abstract int osVersion();
    07. public int compareTo(E o){
    08. return osVersion() - o.osVersion();
    09. }
    10. }
    11.  
    12. class Iphone extends Handphone<Iphone>{
    13. private int version;
    14. public Iphone(int version){
    15. this.version = version;
    16. }
    17. public int osVersion(){
    18. return version;
    19. }
    20. }
    21.  
    22. class <a href="http://www.it165.net/pro/ydad/" target="_blank" class="keylink">Android</a> extends Handphone<Android>{
    23. private int version;
    24. public Android(int version){
    25. this.version = version;
    26. }
    27. public int osVersion(){
    28. return version;
    29. }
    30. }
    31.  
    32. public class WeirdGenerics{
    33. public static void main(String []args){
    34. Iphone i4 = new Iphone(4), i5 = new Iphone(5);
    35. Android a2 = new Android(2), a3 = new Android(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. }

     


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM