Java枚举类型的原理

来源:互联网 发布:斗牛作弊器软件 编辑:程序博客网 时间:2024/06/04 18:46
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.lxq.enumm;  
  2.   
  3. public enum Color  
  4. {  
  5.     RED{  
  6.         public String getName(){  
  7.             return "红色";  
  8.         }  
  9.     }  
  10.     ,GREEN{  
  11.         public String getName(){  
  12.             return "绿色";  
  13.         }  
  14.     }  
  15.     ,YELLOW{  
  16.         public String getName(){  
  17.             return "黄色";  
  18.         }  
  19.     };  
  20.     public abstract String getName();  
  21. }  

如果RED只是一个Color类的一个static final的实例,那么上面的代码就很让了费解了,为什么在枚举类型中可以有一个抽象方法,而每个枚举值可以对其重新实现?

别急,看了我对这个类的测试代码你就明白,测试代码如下:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. import java.lang.reflect.Modifier;  
  2.   
  3. public class EnumDemoFour{  
  4.     public static void main(String[] args){  
  5.         //打印该枚举值的名称  
  6.         System.out.println(Color.RED.getName());  
  7.         //打印该枚举值的类  
  8.         System.out.println(Color.RED.getClass());  
  9.         //打印该枚举值的类的父类  
  10.         System.out.println(Color.RED.getClass().getSuperclass());  
  11.         //打印该枚举值的类的父类的父类  
  12.         System.out.println(Color.RED.getClass().getSuperclass().getSuperclass());  
  13.         //打印该枚举类型的修饰符  
  14.         System.out.println(Modifier.toString(Color.class.getModifiers()));  
  15.     }     
  16.     /*运行结果 
  17.     红色 
  18.     class com.lxq.enumm.Color$1 
  19.     class com.lxq.enumm.Color 
  20.     class java.lang.Enum 
  21.     public abstract*/  
  22. }  

该运行结果首先说明了RED和Color不是同一个类,而是前者是后者的一个子类;同时也说明了enum申明的其实是一个abstract的类,所以Color中可以有抽象方法。

那么,我们应该这么理解枚举类型的原理,首先enum Color继承了java.lang.Enum这个抽象类,但enum Color还是一个抽象类,所以它可以有抽象方法和非抽象方法。

而enum Color中的枚举值变量RED事实上上Color的一个匿名子类,所以它可以实现Color中的抽象方法,这样,当我们调用System.out.println(Color.RED.getName());

就是调用了匿名子类实现的方法。当然这些过程的很多事都有编译器等为我们做了,所以这里的代码很简单。

要是你不明白上面打印的内容,我再提供一个普通的类给你看看,还是类似的效果哦。

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public abstract class TestInnerClass  
  2. {  
  3.     public abstract void dosomething();  
  4.     public static void main(String[] args){  
  5.         TestInnerClass tic=new TestInnerClass(){  
  6.             @Override  
  7.             public void dosomething()  
  8.             {  
  9.                 System.out.println("我是匿名子类");  
  10.             }     
  11.         };  
  12.         tic.dosomething();  
  13.         System.out.println(tic.getClass());  
  14.     }  
  15.     /*输出结果 
  16.     我是匿名子类 
  17.     class TestInnerClass$1 
  18.     */  
  19. }  

最后再附上网上一个使用Java普通类模拟枚举的例子http://blog.csdn.net/xyang81/article/details/7185428,这个例子真的很好。

使用Java普通类模拟枚举

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. import java.util.HashMap;  
  2. import java.util.Map;  
  3.   
  4. /** 
  5.  * 模拟星期中的表示的天,每个星期天都表示一个对象 
  6.  * 1、类中的每一个枚举成员都是该类的一个实例对象 
  7.  * 2、构造函数私有化 
  8.  * 3、提供操作枚举成员的抽象方法和静态方法 
  9.  */  
  10. public abstract class WeekDate {  
  11.     /** 
  12.      * 星期一 
  13.      */  
  14.     public static final WeekDate MON = new WeekDate("MON",0) {//匿名子类  
  15.         @Override  
  16.         public WeekDate nextDay() {  
  17.             return TUES;  
  18.         }  
  19.         @Override  
  20.         public WeekDate preDay() {  
  21.             return SUN;  
  22.         }  
  23.         @Override  
  24.         public String toString() {  
  25.             return "WeekDate.MON";  
  26.         }  
  27.     };    
  28.       
  29.     /** 
  30.      * 星期二 
  31.      */  
  32.     public static final WeekDate TUES = new WeekDate("TUES",1) {  
  33.         @Override  
  34.         public WeekDate nextDay() {  
  35.             return WEDNES;  
  36.         }  
  37.         @Override  
  38.         public WeekDate preDay() {  
  39.             return MON;  
  40.         }  
  41.         @Override  
  42.         public String toString() {  
  43.             return "WeekDate.TUES";  
  44.         }  
  45.     };  
  46.       
  47.     /** 
  48.      * 星期三 
  49.      */  
  50.     public static final WeekDate WEDNES = new WeekDate("WEDNES",2) {  
  51.         @Override  
  52.         public WeekDate nextDay() {  
  53.             return THURS;  
  54.         }  
  55.         @Override  
  56.         public WeekDate preDay() {  
  57.             return TUES;  
  58.         }  
  59.         @Override  
  60.         public String toString() {  
  61.             return "WeekDate.WEDNES";  
  62.         }     
  63.     };  
  64.       
  65.     /** 
  66.      * 星期四 
  67.      */  
  68.     public static final WeekDate THURS = new WeekDate("THURS",3) {  
  69.         @Override  
  70.         public WeekDate nextDay() {  
  71.             return FRI;  
  72.         }  
  73.         @Override  
  74.         public WeekDate preDay() {  
  75.             return WEDNES;  
  76.         }         
  77.         @Override  
  78.         public String toString() {  
  79.             return "WeekDate.THURS";  
  80.         }         
  81.     };  
  82.       
  83.     /** 
  84.      * 星期五 
  85.      */  
  86.     public static final WeekDate FRI = new WeekDate("FRI",4){  
  87.         @Override  
  88.         public WeekDate nextDay() {  
  89.             return SATUR;  
  90.         }  
  91.         @Override  
  92.         public WeekDate preDay() {  
  93.             return THURS;  
  94.         }  
  95.         @Override  
  96.         public String toString() {  
  97.             return "WeekDate.FRI";  
  98.         }  
  99.     };  
  100.       
  101.     /** 
  102.      * 星期六 
  103.      */  
  104.     public static final WeekDate SATUR = new WeekDate("SATUR",5){  
  105.         @Override  
  106.         public WeekDate nextDay() {  
  107.             return SUN;  
  108.         }  
  109.         @Override  
  110.         public WeekDate preDay() {  
  111.             return FRI;  
  112.         }         
  113.         @Override  
  114.         public String toString() {  
  115.             return "WeekDate.SATUR";  
  116.         }         
  117.     };  
  118.       
  119.     /** 
  120.      * 星期日 
  121.      */  
  122.     public static final WeekDate SUN = new WeekDate("SUN",6){  
  123.         @Override  
  124.         public WeekDate nextDay() {  
  125.             return MON;  
  126.         }  
  127.         @Override  
  128.         public WeekDate preDay() {  
  129.             return SATUR;  
  130.         }  
  131.         @Override  
  132.         public String toString() {  
  133.             return "WeekDate.SUN";  
  134.         }  
  135.     };  
  136.       
  137.     private static Map<String, WeekDate> valueMap = new HashMap<String, WeekDate>();  
  138.       
  139.     /** 
  140.      * 枚举名称 
  141.      */  
  142.     private final String name;  
  143.       
  144.     /** 
  145.      * 枚举成员的顺序 
  146.      */  
  147.     private final int ordinal;  
  148.       
  149.     private WeekDate(String name,int ordinal) {  
  150.         this.name = name;  
  151.         this.ordinal = ordinal;  
  152.     }  
  153.       
  154.     /** 
  155.      * 保存枚举成员 
  156.      */  
  157.     private static WeekDate[] values = {  
  158.         MON,TUES,WEDNES,THURS,FRI,SATUR,SUN  
  159.     };  
  160.       
  161.     //初始化  
  162.     static {  
  163.         valueMap.put("MON", values[0]);  
  164.         valueMap.put("TUES", values[1]);  
  165.         valueMap.put("WEDNES", values[2]);  
  166.         valueMap.put("THURS", values[3]);  
  167.         valueMap.put("FRI", values[4]);  
  168.         valueMap.put("SATUR", values[5]);  
  169.         valueMap.put("SUN", values[6]);  
  170.     }  
  171.       
  172.     /** 
  173.      * 下一天 
  174.      * @return 
  175.      */  
  176.     public abstract WeekDate nextDay();  
  177.       
  178.     /** 
  179.      * 前一天 
  180.      * @return 
  181.      */  
  182.     public abstract WeekDate preDay();  
  183.       
  184.     /** 
  185.      * 枚举中的所有成员 
  186.      * @return 
  187.      */  
  188.     public static WeekDate[] values() {  
  189.         return values;  
  190.     }  
  191.       
  192.     /** 
  193.      * 将一个字符串转换成一个枚举成员对象 
  194.      * @param name 枚举名称 
  195.      * @return 枚举对象 
  196.      */  
  197.     public static WeekDate valueOf(String name) {  
  198.         if (name.equalsIgnoreCase("MON")) {  
  199.             return MON;  
  200.         } else if (name.equalsIgnoreCase("TUES")) {  
  201.             return TUES;  
  202.         } else if (name.equalsIgnoreCase("WEDES")) {  
  203.             return WEDNES;  
  204.         } else if (name.equalsIgnoreCase("THURS")) {  
  205.             return THURS;  
  206.         } else if (name.equalsIgnoreCase("FRI")) {  
  207.             return FRI;  
  208.         } else if (name.equalsIgnoreCase("SATUR")) {  
  209.             return SATUR;  
  210.         } else if (name.equalsIgnoreCase("SUN")) {  
  211.             return SUN;  
  212.         } else {  
  213.             throw new IllegalArgumentException("找不到" + name + "枚举类型!");  
  214.         }  
  215.     }  
  216.       
  217.     /** 
  218.      * 优化字符串转枚举对象 
  219.      * @param name 枚举名称 
  220.      * @return 枚举对象 
  221.      */  
  222.     public static WeekDate valueOf_2(String name) {  
  223.         WeekDate value = valueMap.get(name.toUpperCase());  
  224.         if (value == null) {  
  225.             throw new IllegalArgumentException("找不到" + name + "枚举类型!");  
  226.         }  
  227.         return value;  
  228.     }  
  229.     public String getName() {  
  230.         return name;  
  231.     }  
  232.     public int getOrdinal() {  
  233.         return ordinal;  
  234.     }  
  235. }  

使用JDK5.0中提供的枚举特性

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 枚举的应用 
  3.  * 存储每周中的天份 
  4.  */  
  5. public enum WeekDateEnum {  
  6.   
  7.     MON {  
  8.           
  9.         @Override  
  10.         public WeekDateEnum nextDay() {  
  11.             return TUES;  
  12.         }  
  13.           
  14.         @Override  
  15.         public WeekDateEnum preDay() {  
  16.             return SUN;  
  17.         }  
  18.           
  19.     },  TUES {  
  20.           
  21.         @Override  
  22.         public WeekDateEnum nextDay() {  
  23.             return WEDNES;  
  24.         }  
  25.           
  26.         @Override  
  27.         public WeekDateEnum preDay() {  
  28.             return MON;  
  29.         }  
  30.           
  31.     },  WEDNES {  
  32.           
  33.         @Override  
  34.         public WeekDateEnum nextDay() {  
  35.             return THURS;  
  36.         }  
  37.           
  38.         @Override  
  39.         public WeekDateEnum preDay() {  
  40.             return TUES;  
  41.         }  
  42.           
  43.     },  THURS {  
  44.           
  45.         @Override  
  46.         public WeekDateEnum nextDay() {  
  47.             return FRI;  
  48.         }  
  49.           
  50.         @Override  
  51.         public WeekDateEnum preDay() {  
  52.             return WEDNES;  
  53.         }  
  54.           
  55.     },  FRI {  
  56.           
  57.         @Override  
  58.         public WeekDateEnum nextDay() {  
  59.             return SATUR;  
  60.         }  
  61.           
  62.         @Override  
  63.         public WeekDateEnum preDay() {  
  64.             return THURS;  
  65.         }  
  66.           
  67.     },  SATUR {  
  68.           
  69.         @Override  
  70.         public WeekDateEnum nextDay() {  
  71.             return SATUR;  
  72.         }  
  73.           
  74.         @Override  
  75.         public WeekDateEnum preDay() {  
  76.             return FRI;  
  77.         }  
  78.           
  79.     },  SUN {  
  80.           
  81.         @Override  
  82.         public WeekDateEnum nextDay() {  
  83.             return SATUR;  
  84.         }  
  85.           
  86.         @Override  
  87.         public WeekDateEnum preDay() {  
  88.             return MON;  
  89.         }  
  90.           
  91.     };  
  92.   
  93.     private WeekDateEnum() {}  
  94.       
  95.     /** 
  96.      * 下一天 
  97.      * @return 
  98.      */  
  99.     public abstract WeekDateEnum nextDay();  
  100.       
  101.     /** 
  102.      * 前一天 
  103.      * @return 
  104.      */  
  105.     public abstract WeekDateEnum preDay();  
  106.       
  107.     /** 
  108.      * 枚举对象公共的toString方法,可以在case块中反馈自己想要返回的信息 
  109.      */  
  110.     public String toString() {  
  111.         switch (this) {  
  112.         case MON:  
  113.             return "WeekDateEnum.MON";  
  114.         case TUES:  
  115.             return "WeekDateEnum.TUES";  
  116.         case WEDNES:  
  117.             return "WeekDateEnum.WEDNES";  
  118.         case THURS:  
  119.             return "WeekDateEnum.THURS";  
  120.         case FRI:  
  121.             return "WeekDateEnum.FRI";  
  122.         case SATUR:  
  123.             return "WeekDateEnum.SATUR";  
  124.         case SUN:  
  125.             return "WeekDateEnum.SUN";  
  126.         default:  
  127.             return null;  
  128.         }  
  129.     }  
  130. }  

枚举功能测试

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 枚举功能测试 
  3.  */  
  4. public class EnumTest {  
  5.   
  6.     public static void main(String[] args) {  
  7.           
  8.         //使用普通JAVA类模拟枚举的应用  
  9.         WeekDate weekDate = WeekDate.MON;       //获得一个枚举对象  
  10.         //调用枚举中提供的方法  
  11.         System.out.println(weekDate.nextDay());   
  12.         System.out.println(weekDate.preDay());  
  13.         System.out.println(weekDate.getName());  
  14.         //获得枚举成员所在枚举成员列表中的位置  
  15.         System.out.println(weekDate.getOrdinal());  
  16.         //调用某一个枚举成员的方法  
  17.         System.out.println(WeekDate.values()[0].preDay());  
  18.         System.out.println("---------------遍历枚举成员,普通JAVA类模拟--------------------------");  
  19.         for (WeekDate weekDate2 : WeekDate.values()) {  
  20.             System.out.println(weekDate2);  
  21.         }  
  22.           
  23.         System.out.println("\n=================================================================\n");  
  24.           
  25.         //使用JDK中提供的枚举特性功能应用  
  26.         WeekDateEnum weekDateEnum = WeekDateEnum.MON;   //获得一个枚举对象  
  27.         System.out.println(WeekDate.values().length);   //获得枚举成员数量  
  28.         System.out.println(weekDateEnum.name());        //获得枚举的字符串名称  
  29.         System.out.println(weekDateEnum.toString());    //打印枚举对象,已重写toString方法,默认打印枚举的名称  
  30.         System.out.println(weekDateEnum.nextDay().ordinal());   //枚举成员列表中的位置  
  31.         System.out.println(WeekDateEnum.valueOf("FRI").nextDay().ordinal());  
  32.         System.out.println("---------------遍历枚举成员,使用JDK的枚举特性-------------------------");  
  33.         for (WeekDateEnum enumDemo : WeekDateEnum.values()) {  
  34.             System.out.println(enumDemo);  
  35.         }  
  36.           
  37.     }   
  38.       
  39. }  
0 0
原创粉丝点击