zoukankan      html  css  js  c++  java
  • java enum

    Enum+多态,我没说错,不过Enum是不可以被继承的,也不可以继承自别人,只是能实现接口而已,何谈多态?
    不过还是先看看“现象”吧: 
    Java代码  收藏代码
    1. public enum Fruit {  
    2.     APPLE, PEAR, PEACH, ORANGE;  
    3. }  

    以上是一个简单的enum,关于它,我要补充一点: 
    Fruit是java.lang.Enum的子类,准确地说,是Enum<Fruit>的子类,这里出现了一个继承关系,不过这个继承是编译器帮我们做的,我们不能显式地去做。不信的话我们可以试着用一个Enum<Fruit>的引用去指向一个APPLE,肯定是没问题的,我就不再试了。 
    为了更直观地说明这一点,我们来看看Fruit的反编译结果吧: 
    Java代码  收藏代码
    1. package test;  
    2.   
    3.   
    4. public final class Fruit extends Enum  
    5. {  
    6.   
    7.     private Fruit(String s, int i)  
    8.     {  
    9.         super(s, i);  
    10.     }  
    11.   
    12.     public static Fruit[] values()  
    13.     {  
    14.         Fruit afruit[];  
    15.         int i;  
    16.         Fruit afruit1[];  
    17.         System.arraycopy(afruit = ENUM$VALUES, 0, afruit1 = new Fruit[i = afruit.length], 0, i);  
    18.         return afruit1;  
    19.     }  
    20.   
    21.     public static Fruit valueOf(String s)  
    22.     {  
    23.         return (Fruit)Enum.valueOf(test/Fruit, s);  
    24.     }  
    25.   
    26.     public static final Fruit APPLE;  
    27.     public static final Fruit PEAR;  
    28.     public static final Fruit PEACH;  
    29.     public static final Fruit ORANGE;  
    30.     private static final Fruit ENUM$VALUES[];  
    31.   
    32.     static   
    33.     {  
    34.         APPLE = new Fruit("APPLE", 0);  
    35.         PEAR = new Fruit("PEAR", 1);  
    36.         PEACH = new Fruit("PEACH", 2);  
    37.         ORANGE = new Fruit("ORANGE", 3);  
    38.         ENUM$VALUES = (new Fruit[] {  
    39.             APPLE, PEAR, PEACH, ORANGE  
    40.         });  
    41.     }  
    42. }  

    注意这几行: 
    Java代码  收藏代码
    1. public static final Fruit APPLE;  
    2.     public static final Fruit PEAR;  
    3.     public static final Fruit PEACH;  
    4.     public static final Fruit ORANGE;  

    看来JDK Enum的实现也不过就是沿袭了Effective Java中提出的TypeSafeEnum模式,只不过是在编译器和JVM等更底层的级别上提供了支持。 

    至此,至少说明了Fruit和Enum的继承关系,但问题是:现在不能继续再从Fruit派生子类,那么哪来的多态呢? 

    还是再多写点代码吧: 
    Java代码  收藏代码
    1. public enum Fruit {  
    2.     APPLE {  
    3.   
    4.         public void test() {  
    5.             System.out.println("I am an apple.");  
    6.         }  
    7.     },  
    8.     PEAR {  
    9.   
    10.         public void test() {  
    11.             System.out.println("I am a pear.");  
    12.         }  
    13.     },  
    14.     PEACH {  
    15.   
    16.         public void test() {  
    17.             System.out.println("I am a peach.");  
    18.         }  
    19.     },  
    20.     ORANGE;  
    21.   
    22.     public void test() {  
    23.         System.out.println("I am a fruit.");  
    24.     }  
    25. }  

    其中,只有Orange没有Overide test()方法; 
    我们在主函数中调用它们: 
    Java代码  收藏代码
    1. public static void main(String[] args) {  
    2.         Fruit.APPLE.test();  
    3.         Fruit.PEAR.test();  
    4.         Fruit.PEACH.test();  
    5.         Fruit.ORANGE.test();  
    6.     }  

    输出结果: 
    引用
    I am an apple. 
    I am a pear. 
    I am a peach. 
    I am a fruit.

    可以看到,重新定义了test方法的APPLE,PEAR,PEACH覆盖了从父类继承过来的默认行为,而未从新定义test方法的ORANGE却沿袭了父类的行为,多态性在这里展现出来了。 

    那么我们刚才明明看见过Fruit的反编译结果,没有任何新类继承自Fruit,那么这些多态行为是哪里冒出来的呢?说它是“多态”是否准确呢? 
    其实,Fruit类在这个时候已经发生了微妙的变化,一切都与JDK的Enum的实现有关,我们现在可以到编译结果目录下面看看: 
     
    怎么除了Fruit.class之外,还多了几个貌似是内部类的class文件??也许看到这里我们能有点线索了,不过还是在这个时候在看看反编译结果吧,看看它到底在搞什么鬼: 
    Java代码  收藏代码
    1. // Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.  
    2. // Jad home page: http://www.geocities.com/kpdus/jad.html  
    3. // Decompiler options: packimports(3)   
    4. // Source File Name:   Fruit.java  
    5.   
    6. package test;  
    7.   
    8. import java.io.PrintStream;  
    9.   
    10. public class Fruit extends Enum  
    11. {  
    12.   
    13.     private Fruit(String s, int i)  
    14.     {  
    15.         super(s, i);  
    16.     }  
    17.   
    18.     public void test()  
    19.     {  
    20.         System.out.println("I am a fruit.");  
    21.     }  
    22.   
    23.     public static Fruit[] values()  
    24.     {  
    25.         Fruit afruit[];  
    26.         int i;  
    27.         Fruit afruit1[];  
    28.         System.arraycopy(afruit = ENUM$VALUES, 0, afruit1 = new Fruit[i = afruit.length], 0, i);  
    29.         return afruit1;  
    30.     }  
    31.   
    32.     public static Fruit valueOf(String s)  
    33.     {  
    34.         return (Fruit)Enum.valueOf(test/Fruit, s);  
    35.     }  
    36.   
    37.     Fruit(String s, int i, Fruit fruit)  
    38.     {  
    39.         this(s, i);  
    40.     }  
    41.   
    42.     public static final Fruit APPLE;  
    43.     public static final Fruit PEAR;  
    44.     public static final Fruit PEACH;  
    45.     public static final Fruit ORANGE;  
    46.     private static final Fruit ENUM$VALUES[];  
    47.   
    48.     static   
    49.     {  
    50.         APPLE = new Fruit("APPLE", 0) {  
    51.   
    52.             public void test()  
    53.             {  
    54.                 System.out.println("I am an apple.");  
    55.             }  
    56.   
    57.         };  
    58.         PEAR = new Fruit("PEAR", 1) {  
    59.   
    60.             public void test()  
    61.             {  
    62.                 System.out.println("I am a pear.");  
    63.             }  
    64.   
    65.         };  
    66.         PEACH = new Fruit("PEACH", 2) {  
    67.   
    68.             public void test()  
    69.             {  
    70.                 System.out.println("I am a peach.");  
    71.             }  
    72.   
    73.         };  
    74.         ORANGE = new Fruit("ORANGE", 3);  
    75.         ENUM$VALUES = (new Fruit[] {  
    76.             APPLE, PEAR, PEACH, ORANGE  
    77.         });  
    78.     }  
    79. }  

    注意这段代码: 
    Java代码  收藏代码
    1. static   
    2.     {  
    3.         APPLE = new Fruit("APPLE", 0) {  
    4.   
    5.             public void test()  
    6.             {  
    7.                 System.out.println("I am an apple.");  
    8.             }  
    9.   
    10.         };  
    11.         PEAR = new Fruit("PEAR", 1) {  
    12.   
    13.             public void test()  
    14.             {  
    15.                 System.out.println("I am a pear.");  
    16.             }  
    17.   
    18.         };  
    19.         PEACH = new Fruit("PEACH", 2) {  
    20.   
    21.             public void test()  
    22.             {  
    23.                 System.out.println("I am a peach.");  
    24.             }  
    25.   
    26.         };  
    27.         ORANGE = new Fruit("ORANGE", 3);  

    这个时候的APPLE,PEAR,PEACH已经以匿名内部类的方式对Fruit进行了Overide,自然体现出了多态,多出的那三个疑似内部类的class文件也就是它们!而ORANGE,没有重写test方法,仍然以一个Fruit实例的形式出现。 

    关于Enum为什么会有多态大概也就这么点猫腻了,那我们来考虑一下它有多大价值吧? 

    我们或许可以利用这一点来改造Strategy模式,传统的Strategy会产生出稍微多一些的父类、子类,而如果用Enum的话,“一个类”(对程序作者来讲)就能搞定,能简化一下类层次,再说了,用枚举来表示区分各种不同策略也是很合情理的,所以,Java Enum的这点小小特性感觉还是比较有前途发挥一些作用的,起码在代码组织上; 
    更多应用可能或是局限性就还需要逐步在实际应用中摸索。
  • 相关阅读:
    Jquery中的this是什么类型
    sorl的schema配置
    vim下常用的命令
    虚拟机克隆
    mysql突然无法连接:the driver has not received any packets from server communications link
    利用DOM的方式点击切换图片及修改文字
    javascript简易日历制作
    markdown数学公式输入指南
    Object.assign()
    引入css的方式
  • 原文地址:https://www.cnblogs.com/diegodu/p/6256989.html
Copyright © 2011-2022 走看看