对JAVA枚举类型的学习

本文详细介绍了Java SE 1.5引入的枚举类型,包括定义方法、基本要求及其实现原理。并展示了如何在枚举中添加属性、方法以及实现接口的例子。

java SE 1.5以后的版本中,引入了一个新的引用类型----枚举类型。枚举类型指的是由一组固定的常量组合成的合法值类型,例如一年的四季,一个星期的7天,红绿蓝三色、状态的可用与不可用等,都是枚举类型的示例。

java中定义枚举的方法如下:

Code:
  1. public enum Year{SPRING,SUMMER,FALL,WINTER};      

java中定义枚举的基本要求有:

1.使用关键字enum。

2.类型名称,比如这里的Year。

3.一串允许的值,比如上面定义的春夏秋冬四季。

4。枚举可以单独定义在一个文件中,也可以嵌在其他Java类中。

除了这样的定义以外,用户还有一些其他选择:

1。枚举可以实现一个或多个接口(interface)。

2。可以定义新的变量和方法。

3。可以定义根据具体枚举值而相异的类。

java枚举类的原理也比较简单,就是在编译器编译的时候,枚举类型会被转换成为static final类型的一个类。比如以上定义枚举类被编译后的代码如下所示:

Code:
  1. //源代码   
  2. public class Test   
  3. {   
  4.     public enum Year{SPRING,SUMMER,FALL,WINTER};   
  5.     public static void main(String[] args){}   
  6. }  
Code:
  1. //编译后生成的class文件经过反编译以后的代码   
  2. public class Test   
  3. {   
  4.     public static final class Year extends Enum   
  5.     {   
  6.   
  7.         public static Year[] values()   
  8.         {   
  9.             return (Year[])$VALUES.clone();   
  10.         }   
  11.   
  12.         public static Year valueOf(String s)   
  13.         {   
  14.             return (Year)Enum.valueOf(Test$Year, s);   
  15.         }   
  16.   
  17.         public static final Year SPRING;   
  18.         public static final Year SUMMER;   
  19.         public static final Year FALL;   
  20.         public static final Year WINTER;   
  21.         private static final Year $VALUES[];   
  22.   
  23.         static    
  24.         {   
  25.             SPRING = new Year("SPRING"0);   
  26.             SUMMER = new Year("SUMMER"1);   
  27.             FALL = new Year("FALL"2);   
  28.             WINTER = new Year("WINTER"3);   
  29.             $VALUES = (new Year[] {   
  30.                 SPRING, SUMMER, FALL, WINTER   
  31.             });   
  32.         }   
  33.   
  34.         private Year(String s, int i)   
  35.         {   
  36.             super(s, i);   
  37.         }   
  38.     }   
  39.   
  40.   
  41.     public Test()   
  42.     {   
  43.     }   
  44.   
  45.     public static void main(String args[])   
  46.     {   
  47.     }   
  48. }  

 那么通过看编译后生成的代码可以看出,大概有这么几个规律:

1.定义的枚举变量变成了一个类名,并且继承了java.lang.Enum类。

2.枚举常量被变成了static final Year类型的。并且多了一个枚举类类型的数组变量private static final Year $VALUES[];

3.枚举类中多了这么几个方法。

Code:
  1. public static Year[] values(){...}   //返回该枚举对象定义的一个枚举类型数组。    
  2. public static Year valueOf(String s){...}//根据传入的字符串返回相应的枚举值。      
  3. private Year(String s, int i){...}   //构造方法  

 4.多了一个静态执行块。

Code:
  1. static        
  2.         {       
  3.             SPRING = new Year("SPRING"0);//调用构造方法类给枚举常量给值。   
  4.             SUMMER = new Year("SUMMER"1);       
  5.             FALL = new Year("FALL"2);       
  6.             WINTER = new Year("WINTER"3);       
  7.             $VALUES = (new Year[] {  //初始化枚举类类型数组     
  8.                 SPRING, SUMMER, FALL, WINTER       
  9.             });       
  10.         }      

所以枚举类型的值是直接用“枚举名.枚举值”来访问的,使用如下所示。

Code:
  1. public class Test   
  2. {   
  3.     enum Year{SPRING,SUMMER,FALL,WINTER};   
  4.     public static void main(String[] args){   
  5.         Year thisYear = Year.SPRING;   
  6.         Year[] ty = Year.values();   
  7.         for(Year tyear : ty){   
  8.             System.out.println(tyear);   
  9.         }   
  10.         Year yearSeason = Year.valueOf("SPRING");   
  11.         switch(yearSeason){   
  12.             case SPRING:   
  13.                 System.out.println("春天");break;   
  14.             case SUMMER:   
  15.                 System.out.println("夏天");break;   
  16.             case FALL:   
  17.                 System.out.println("秋天");break;   
  18.             case WINTER:   
  19.                 System.out.println("冬天");break;   
  20.             default:   
  21.                 System.out.println("四季平安");break;   
  22.         }   
  23.     }   
  24. }  

运行结果:

SPRING
SUMMER
FALL
WINTER
春天

由于枚举类型就是java.lang.Enum类的子类,因此,在枚举类型中可以添加属性,构造器和方法,并可以实现任意的接口,而且提供了所有Object类的方法,使用示例如下:

Code:
  1. //sun公司提供的enum使用示例   
  2. public class PlanetTest{   
  3.     public enum Planet {   
  4.         MERCURY (3.303e+232.4397e6),   
  5.         VENUS   (4.869e+246.0518e6),   
  6.         EARTH   (5.976e+246.37814e6),   
  7.         MARS    (6.421e+233.3972e6),   
  8.         JUPITER (1.9e+27,   7.1492e7),   
  9.         SATURN  (5.688e+266.0268e7),   
  10.         URANUS  (8.686e+252.5559e7),   
  11.         NEPTUNE (1.024e+262.4746e7),   
  12.         PLUTO   (1.27e+221.137e6);   
  13.   
  14.   
  15.         private final double mass;   // in kilograms   
  16.         private final double radius; // in meters   
  17.   
  18.         Planet(double mass, double radius)   
  19.         {   
  20.             this.mass = mass;   
  21.             this.radius = radius;   
  22.         }   
  23.   
  24.         private double mass()   { return mass; }   
  25.         private double radius() { return radius; }   
  26.         // universal gravitational constant  (m3 kg-1 s-2)   
  27.         public static final double G = 6.67300E-11;   
  28.   
  29.         double surfaceGravity() {   
  30.             return G * mass / (radius * radius);   
  31.         }   
  32.         double surfaceWeight(double otherMass) {   
  33.             return otherMass * surfaceGravity();   
  34.         }      
  35.     }    
  36.     public static void main(String[] args){   
  37.             for(int i = 0;i<Planet.values().length;i++){   
  38.                 System.out.println(Planet.values()[i]);   
  39.                 //System.out.println(Planet.MERCURY);   
  40.                 //System.out.println(Planet.values()[i].mass());   
  41.                 //System.out.println(Planet.values()[i].surfaceGravity());   
  42.                 //System.out.println(Planet.values()[i].surfaceWeight(1.27e+22));   
  43.             }   
  44.         }   
  45. }  

以上使用方法大体规律为:

构造方法,和枚举值中的参数,参数的出处(如上例的mass和radius)必须要联系起来。其他变量和方法没什么特殊要求。看下面代码所示:

Code:
  1. MERCURY (3.303e+232.4397e6),   
  2. 以及   
  3. private final double mass;   // in kilograms   
  4. private final double radius; // in meters   
  5. 以及   
  6. Planet(double mass, double radius){   
  7.     this.mass = mass;   
  8.     this.radius = radius;   
  9. }  

为什么上面要说他们必须要有联系呢。先别多说,看看反编译后的代码。如下所示:

Code:
  1. import java.io.PrintStream;   
  2.   
  3. public class PlanetTest   
  4. {   
  5.     public static final class Planet extends Enum   
  6.     {   
  7.   
  8.         public static Planet[] values()   
  9.         {   
  10.             return (Planet[])$VALUES.clone();   
  11.         }   
  12.   
  13.         public static Planet valueOf(String s)   
  14.         {   
  15.             return (Planet)Enum.valueOf(PlanetTest$Planet, s);   
  16.         }   
  17.   
  18.         private double mass()   
  19.         {   
  20.             return mass;   
  21.         }   
  22.   
  23.         private double radius()   
  24.         {   
  25.             return radius;   
  26.         }   
  27.   
  28.         double surfaceGravity()   
  29.         {   
  30.             return (6.6729999999999999E-011D * mass) / (radius * radius);   
  31.         }   
  32.   
  33.         double surfaceWeight(double d)   
  34.         {   
  35.             return d * surfaceGravity();   
  36.         }   
  37.   
  38.         public static final Planet MERCURY;   
  39.         public static final Planet VENUS;   
  40.         public static final Planet EARTH;   
  41.         public static final Planet MARS;   
  42.         public static final Planet JUPITER;   
  43.         public static final Planet SATURN;   
  44.         public static final Planet URANUS;   
  45.         public static final Planet NEPTUNE;   
  46.         public static final Planet PLUTO;   
  47.         private final double mass;   
  48.         private final double radius;   
  49.         public static final double G = 6.6729999999999999E-011D;   
  50.         private static final Planet $VALUES[];   
  51.   
  52.         static    
  53.         {   
  54.             MERCURY = new Planet("MERCURY"03.3030000000000001E+023D, 2439700D);   
  55.             VENUS = new Planet("VENUS"14.8690000000000001E+024D, 6051800D);   
  56.             EARTH = new Planet("EARTH"25.9760000000000004E+024D, 6378140D);   
  57.             MARS = new Planet("MARS"36.4209999999999999E+023D, 3397200D);   
  58.             JUPITER = new Planet("JUPITER"41.9000000000000001E+027D, 71492000D);   
  59.             SATURN = new Planet("SATURN"55.6879999999999998E+026D, 60268000D);   
  60.             URANUS = new Planet("URANUS"68.686E+025D, 25559000D);   
  61.             NEPTUNE = new Planet("NEPTUNE"71.0239999999999999E+026D, 24746000D);   
  62.             PLUTO = new Planet("PLUTO"81.2700000000000001E+022D, 1137000D);   
  63.             $VALUES = (new Planet[] {   
  64.                 MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE, PLUTO   
  65.             });   
  66.         }   
  67.   
  68.         private Planet(String s, int i, double d, double d1)   
  69.         {   
  70.             super(s, i);   
  71.             mass = d;   
  72.             radius = d1;   
  73.         }   
  74.     }   
  75.   
  76.   
  77.     public PlanetTest()   
  78.     {   
  79.     }   
  80.   
  81.     public static void main(String args[])   
  82.     {   
  83.         for(int i = 0; i < Planet.values().length; i++)   
  84.             System.out.println(Planet.values()[i]);   
  85.   
  86.     }   
  87. }  

通过观察不难发现有以下几个特点:

1.构造方法多了两个参数,且为private的。private Planet(String s, int i, double d, double d1)。为什么会这样呢,首先private 就是为了方式实例化该类。其次多余的两个参数就是源代码中构造方法的两个参数,方法体中包含父类构造方法调用和源文件中构造方法的方法体。

2.静态执行快中,调用了构造方法,构造方法的参数为4个,后面多出的两个参数也正是枚举常量后的参数MERCURY (3.303e+23, 2.4397e6)...。

所以,编译器在编译的过程中是根据构造方法来增加编译后构造方法中多余的参数。

下面一个实例是利用枚举来实现加减乘除运算。

Code:
  1. public class OperationTest {   
  2.     public enum Operation{   
  3.         ADD{double eval(double x,double y){return x+y;}},   
  4.         SUB{double eval(double x,double y){return x-y;}},   
  5.         MUL{double eval(double x,double y){return x*y;}},   
  6.         DIV{double eval(double x,double y){return x/y;}};   
  7.   
  8.         abstract double eval(double x,double y);   
  9.     }   
  10.     public static void main(String[] args)    
  11.     {   
  12.         for(int i = 0;i<Operation.values().length;i++){   
  13.             System.out.println(Operation.values()[i].eval(3,4));   
  14.         }   
  15.     }   
  16. }  

运行结果:

7.0
-1.0
12.0
0.75

第一次些学习笔记,不知道写的对不对,反正先写出来,有错误希望各位老师和同学指出我好改正。

差点忘说了。网上的资料很多,其中有一篇是最全的,如下:

http://blog.csdn.net/casularm/archive/2004/12/19/221783.aspx

 jdk 1.5 枚举替代类:http://blog.csdn.net/mdog26/archive/2008/11/04/3210274.aspx

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值