前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java枚举类型的原理

Java枚举类型的原理

作者头像
汤高
发布2018-03-28 11:54:35
1.4K0
发布2018-03-28 11:54:35
举报
文章被收录于专栏:积累沉淀积累沉淀
代码语言:javascript
复制
 package com.lxq.enumm;  
 public enum Color  
 {  
     RED{  
  public String getName(){  
  return "红色";  
         }  
     }  
     ,GREEN{  
  public String getName(){  
  return "绿色";  
         }  
     }  
     ,YELLOW{  
  public String getName(){  
  return "黄色";  
         }  
     };  
  public abstract String getName();  
 }  

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

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

代码语言:javascript
复制
 import java.lang.reflect.Modifier;  
  
 public class EnumDemoFour{  
  public static void main(String[] args){  
  //打印该枚举值的名称 
         System.out.println(Color.RED.getName());  
  //打印该枚举值的类 
         System.out.println(Color.RED.getClass());  
  //打印该枚举值的类的父类 
         System.out.println(Color.RED.getClass().getSuperclass());  
  //打印该枚举值的类的父类的父类 
         System.out.println(Color.RED.getClass().getSuperclass().getSuperclass());  
  //打印该枚举类型的修饰符 
         System.out.println(Modifier.toString(Color.class.getModifiers()));  
     }     
  /*运行结果 
     红色 
     class com.lxq.enumm.Color$1 
     class com.lxq.enumm.Color 
     class java.lang.Enum 
     public abstract*/ 
 }  

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

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

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

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

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

代码语言:javascript
复制
 public abstract class TestInnerClass  
 {  
  public abstract void dosomething();  
  public static void main(String[] args){  
         TestInnerClass tic=new TestInnerClass(){  
  @Override 
  public void dosomething()  
             {  
                 System.out.println("我是匿名子类");  
             }     
         };  
         tic.dosomething();  
         System.out.println(tic.getClass());  
     }  
  /*输出结果 
     我是匿名子类 
     class TestInnerClass$1 
     */ 
 }  

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

使用Java普通类模拟枚举

代码语言:javascript
复制
 import java.util.HashMap;  
 import java.util.Map;  
  
 /** 
  * 模拟星期中的表示的天,每个星期天都表示一个对象 
  * 1、类中的每一个枚举成员都是该类的一个实例对象 
  * 2、构造函数私有化 
  * 3、提供操作枚举成员的抽象方法和静态方法 
  */ 
 public abstract class WeekDate {  
  /** 
      * 星期一 
      */ 
  public static final WeekDate MON = new WeekDate("MON",0) {//匿名子类 
  @Override 
  public WeekDate nextDay() {  
  return TUES;  
         }  
  @Override 
  public WeekDate preDay() {  
  return SUN;  
         }  
  @Override 
  public String toString() {  
  return "WeekDate.MON";  
         }  
     };    
  
  /** 
      * 星期二 
      */ 
  public static final WeekDate TUES = new WeekDate("TUES",1) {  
  @Override 
  public WeekDate nextDay() {  
  return WEDNES;  
         }  
  @Override 
  public WeekDate preDay() {  
  return MON;  
         }  
  @Override 
  public String toString() {  
  return "WeekDate.TUES";  
         }  
     };  
  
  /** 
      * 星期三 
      */ 
  public static final WeekDate WEDNES = new WeekDate("WEDNES",2) {  
  @Override 
  public WeekDate nextDay() {  
  return THURS;  
         }  
  @Override 
  public WeekDate preDay() {  
  return TUES;  
         }  
  @Override 
  public String toString() {  
  return "WeekDate.WEDNES";  
         }     
     };  
  
  /** 
      * 星期四 
      */ 
  public static final WeekDate THURS = new WeekDate("THURS",3) {  
  @Override 
  public WeekDate nextDay() {  
  return FRI;  
         }  
  @Override 
  public WeekDate preDay() {  
  return WEDNES;  
         }         
  @Override 
  public String toString() {  
  return "WeekDate.THURS";  
         }         
     };  
  
  /** 
      * 星期五 
      */ 
  public static final WeekDate FRI = new WeekDate("FRI",4){  
  @Override 
  public WeekDate nextDay() {  
  return SATUR;  
         }  
  @Override 
  public WeekDate preDay() {  
  return THURS;  
         }  
  @Override 
  public String toString() {  
  return "WeekDate.FRI";  
         }  
     };  
  
  /** 
      * 星期六 
      */ 
  public static final WeekDate SATUR = new WeekDate("SATUR",5){  
  @Override 
  public WeekDate nextDay() {  
  return SUN;  
         }  
  @Override 
  public WeekDate preDay() {  
  return FRI;  
         }         
  @Override 
  public String toString() {  
  return "WeekDate.SATUR";  
         }         
     };  
  
  /** 
      * 星期日 
      */ 
  public static final WeekDate SUN = new WeekDate("SUN",6){  
  @Override 
  public WeekDate nextDay() {  
  return MON;  
         }  
  @Override 
  public WeekDate preDay() {  
  return SATUR;  
         }  
  @Override 
  public String toString() {  
  return "WeekDate.SUN";  
         }  
     };  
  
  private static Map<String, WeekDate> valueMap = new HashMap<String, WeekDate>();  
  
  /** 
      * 枚举名称 
      */ 
  private final String name;  
  
  /** 
      * 枚举成员的顺序 
      */ 
  private final int ordinal;  
  
  private WeekDate(String name,int ordinal) {  
  this.name = name;  
  this.ordinal = ordinal;  
     }  
  
  /** 
      * 保存枚举成员 
      */ 
  private static WeekDate[] values = {  
         MON,TUES,WEDNES,THURS,FRI,SATUR,SUN  
     };  
  
  //初始化 
  static {  
         valueMap.put("MON", values[0]);  
         valueMap.put("TUES", values[1]);  
         valueMap.put("WEDNES", values[2]);  
         valueMap.put("THURS", values[3]);  
         valueMap.put("FRI", values[4]);  
         valueMap.put("SATUR", values[5]);  
         valueMap.put("SUN", values[6]);  
     }  
  
  /** 
      * 下一天 
      * @return 
      */ 
  public abstract WeekDate nextDay();  
  
  /** 
      * 前一天 
      * @return 
      */ 
  public abstract WeekDate preDay();  
  
  /** 
      * 枚举中的所有成员 
      * @return 
      */ 
  public static WeekDate[] values() {  
  return values;  
     }  
  
  /** 
      * 将一个字符串转换成一个枚举成员对象 
      * @param name 枚举名称 
      * @return 枚举对象 
      */ 
  public static WeekDate valueOf(String name) {  
  if (name.equalsIgnoreCase("MON")) {  
  return MON;  
         } else if (name.equalsIgnoreCase("TUES")) {  
  return TUES;  
         } else if (name.equalsIgnoreCase("WEDES")) {  
  return WEDNES;  
         } else if (name.equalsIgnoreCase("THURS")) {  
  return THURS;  
         } else if (name.equalsIgnoreCase("FRI")) {  
  return FRI;  
         } else if (name.equalsIgnoreCase("SATUR")) {  
  return SATUR;  
         } else if (name.equalsIgnoreCase("SUN")) {  
  return SUN;  
         } else {  
  throw new IllegalArgumentException("找不到" + name + "枚举类型!");  
         }  
     }  
  
  /** 
      * 优化字符串转枚举对象 
      * @param name 枚举名称 
      * @return 枚举对象 
      */ 
  public static WeekDate valueOf_2(String name) {  
         WeekDate value = valueMap.get(name.toUpperCase());  
  if (value == null) {  
  throw new IllegalArgumentException("找不到" + name + "枚举类型!");  
         }  
  return value;  
     }  
  public String getName() {  
  return name;  
     }  
  public int getOrdinal() {  
  return ordinal;  
     }  
 }  

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

代码语言:javascript
复制
 /** 
  * 枚举的应用 
  * 存储每周中的天份 
  */ 
 public enum WeekDateEnum {  
  
     MON {  
  
  @Override 
  public WeekDateEnum nextDay() {  
  return TUES;  
         }  
  
  @Override 
  public WeekDateEnum preDay() {  
  return SUN;  
         }  
  
     },  TUES {  
  
  @Override 
  public WeekDateEnum nextDay() {  
  return WEDNES;  
         }  
  
  @Override 
  public WeekDateEnum preDay() {  
  return MON;  
         }  
  
     },  WEDNES {  
  
  @Override 
  public WeekDateEnum nextDay() {  
  return THURS;  
         }  
  
  @Override 
  public WeekDateEnum preDay() {  
  return TUES;  
         }  
  
     },  THURS {  
  
  @Override 
  public WeekDateEnum nextDay() {  
  return FRI;  
         }  
  
  @Override 
  public WeekDateEnum preDay() {  
  return WEDNES;  
         }  
  
     },  FRI {  
  
  @Override 
  public WeekDateEnum nextDay() {  
  return SATUR;  
         }  
  
  @Override 
  public WeekDateEnum preDay() {  
  return THURS;  
         }  
  
     },  SATUR {  
  
  @Override 
  public WeekDateEnum nextDay() {  
  return SATUR;  
         }  
  
  @Override 
  public WeekDateEnum preDay() {  
  return FRI;  
         }  
  
     },  SUN {  
  
  @Override 
  public WeekDateEnum nextDay() {  
  return SATUR;  
         }  
  
  @Override 
  public WeekDateEnum preDay() {  
  return MON;  
         }  
  
     };  
  
  private WeekDateEnum() {}  
  
  /** 
      * 下一天 
      * @return 
      */ 
  public abstract WeekDateEnum nextDay();  
  
  /** 
      * 前一天 
      * @return 
      */ 
  public abstract WeekDateEnum preDay();  
  
  /** 
      * 枚举对象公共的toString方法,可以在case块中反馈自己想要返回的信息 
      */ 
  public String toString() {  
  switch (this) {  
  case MON:  
  return "WeekDateEnum.MON";  
  case TUES:  
  return "WeekDateEnum.TUES";  
  case WEDNES:  
  return "WeekDateEnum.WEDNES";  
  case THURS:  
  return "WeekDateEnum.THURS";  
  case FRI:  
  return "WeekDateEnum.FRI";  
  case SATUR:  
  return "WeekDateEnum.SATUR";  
  case SUN:  
  return "WeekDateEnum.SUN";  
  default:  
  return null;  
         }  
     }  
 }  

枚举功能测试

代码语言:javascript
复制
 /** 
  * 枚举功能测试 
  */ 
 public class EnumTest {  
  
  public static void main(String[] args) {  
  
  //使用普通JAVA类模拟枚举的应用 
         WeekDate weekDate = WeekDate.MON;       //获得一个枚举对象 
  //调用枚举中提供的方法 
         System.out.println(weekDate.nextDay());   
         System.out.println(weekDate.preDay());  
         System.out.println(weekDate.getName());  
  //获得枚举成员所在枚举成员列表中的位置 
         System.out.println(weekDate.getOrdinal());  
  //调用某一个枚举成员的方法 
         System.out.println(WeekDate.values()[0].preDay());  
         System.out.println("---------------遍历枚举成员,普通JAVA类模拟--------------------------");  
  for (WeekDate weekDate2 : WeekDate.values()) {  
             System.out.println(weekDate2);  
         }  
  
         System.out.println("\n=================================================================\n");  
  
  //使用JDK中提供的枚举特性功能应用 
         WeekDateEnum weekDateEnum = WeekDateEnum.MON;   //获得一个枚举对象 
         System.out.println(WeekDate.values().length);   //获得枚举成员数量 
         System.out.println(weekDateEnum.name());        //获得枚举的字符串名称 
         System.out.println(weekDateEnum.toString());    //打印枚举对象,已重写toString方法,默认打印枚举的名称 
         System.out.println(weekDateEnum.nextDay().ordinal());   //枚举成员列表中的位置 
         System.out.println(WeekDateEnum.valueOf("FRI").nextDay().ordinal());  
         System.out.println("---------------遍历枚举成员,使用JDK的枚举特性-------------------------");  
  for (WeekDateEnum enumDemo : WeekDateEnum.values()) {  
             System.out.println(enumDemo);  
         }  
  
     }   
  
 }      
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档