
2007年09月24日 10:26:30
Java5新特征之新特征之枚举
|
Java5新特征之枚举 本文为mercyblitz个人原创,不能用于商业行为,转载请申明出处。 枚举是Java5(Tiger)中新增的一种类型,这个类型是为了弥补Java不支持枚举类型的遗憾。 首先,给大家枚举一个总的印象。枚举是一种特殊的“类”,不是一种接口,它的枚举值都是一个枚举类型的实例。下面我们来具体讲讲枚举。 一、创建一个枚举 [list=1]package com.mercy.tiger; public enum EnumOne { One,TWO,Three } 很简单,有点像创建一个类,事实上他就是“类”,特殊的“类”。看看第三行,这里是什么东西啊?其实枚举就是一些“常熟”,这些常熟在这个集合中。这里就是One,TWO,Three就在EnumOne集合中。这里值得说明的是,One这三个都是EnumOne的实例,这就是枚举的特殊性。 怎么来用它呢? [list=1]public static void main(String[] args) [list=1]{ EnumOne one=EnumOne.One; System.out.println(one); // result : One } 这里我们讲到了怎么定义一个接口,并且简单地打印出来结果。 [list=1][list=1]二、内置枚举 我们来写一个内置(写在一个类的内部)的枚举 [list=1] public class InnerEnum { private enum ALPHABEAT{A,B,C} public static void main(String[] args) { ALPHABEAT a=ALPHABEAT.A; } } 我们在这里可以看出ALPHABEAT是个静态枚举类型,所以在它前面加个static 也没有关系。 三、迭代枚举 我们在这之前,我们应该讲讲枚举的“类”的特性,但是他又不是类(矛盾?)。 我们要迭代枚举的话,我们要用到这个静态方法values(),返回一个对应的枚举数组。 这个方法是JVM内部生成的,给所有的枚举类型的方法,所以枚举很特殊,有“类”性。 [list=1]private enum ALPHABEAT{A,B,C} public static void main(String[] args) { // TODO Auto-generated method stub for(ALPHABEAT a : ALPHABEAT.values()) { System.out.println(a); } } 其结果是:A B C 四、高级内容 恐怕在我们日常中使用了很多枚举,比如把枚举作为条件,比如在switch语句中 使用。 前面可能提示性地说到,枚举值是常量,所以可以作为swtich中的case条件。在用前 面的例子: [list=1] ALPHABEAT a=ALPHABEAT.A; switch(a) { case ALPHABEAT.A:; case ALPHABEAT.B:; case ALPHABEAT.C:; } 很抱歉,这个例子是错的。你会问错在哪里啦?我告诉你美剧的引用是不能作为case条件的。所以我们只能这么做: [list=1]switch(a) { //caseALPHABEAT.A:; //caseALPHABEAT.B:; //caseALPHABEAT.C:; case A: case B: case C: } 好了,点到为止,会用就好了啦!上面的东西可能会引起争议...... 好了,我们在说说枚举的“类”性... 1.添加方法: 喔! [list=1] public enum EnumWithMethod { Enum1,Enum2,Enum3; public String getName() { return this.getName(); } } 发现没有,还有this引用哦!你说它有类性吗?还有令你更吃惊的东西: 我们可以定义main方法,不行试试: [list=1] public enum EnumWithMethod { Enum1,Enum2,Enum3; public String getName() { return this.getName(); } public static void main(String[] args) { EnumWithMethod e1=EnumWithMethod.Enum1; System.out.println(e1.getName()); } } [list=1][list=1]一定可以编译,最好不要运行它,结果你会很郁闷的!(这个原因,这里不说了) 2.实现接口: [list=1]枚举可以接口,肯定嘛,能够定义方法,肯定可以实现接口嘛。 public enumEnumImplementsInferface implementsForImpl { E1,E2; public voidmethod() { //DO Nothing } } interfaceForImpl{ public voidmethod(); } 3.不能扩展与不能被扩展: 你会发现你的枚举在定义的时候不能extends其他的类,也不能被extends。 // enumA extends Object{} // classExtendsEnum extends EnumImplementsInferface{} 自然你会想到这里方法不能是abstract的,其实方法都是final方法,不是吗? 对于为什么不能继承或者被继承,你可以去思考,我觉得应该两方面来看,正方:为什么要继承呢?枚举是常熟集合,继承有什么用呢?我可以任意的取值,并且不需要通过继承来达到扩展的目的。反方:继承可以提高重用性,特别是一些方法的重用等等。所以,未来怎么走,看SUN的啦! 4.特殊规定: 若你比较细心或者有怀疑精神的话,你可能会发现枚举值只能在对最前段定义, 方法等等都在后面定义,试试吧! 5.构造器: 枚举有构造器,但是构造器只能用private限定。默认也是private,这也就是 说枚举通过new关键字不能实例化。 privateEnumWithMethod() { } 这里的话,我们又看到了“类”性。 6.特殊“值”类: 既然有构造器,那么构造器就可以带参数,所以我们构造带有参数的实例。看下 下面的代码: [list=1] public enum EnumVauleClass { EVC1("No.1"),EVC2("No.2"),EVC3("No.3"); private String name; private EnumVauleClass(String name) { this.name=name; } public String getName() { return name; } public static void main(String[] args) { EnumVauleClass evc1=EnumVauleClass.EVC1; out.println(evc1); } } [list=1]这里我们可以看出来,我们实例化了三个实例变量EVC1-EVC3,看到14行,是否发现我们这里的实例并没有带有参数在main方法中!?其实这正是我们要说的我们的类实例是定义在枚举类里面的,我们仅仅引用一个常量实例。这里所说都是基础,为后面的“值”类做铺垫。 再说“值”类,我们改改代码: [list=1] public enum EnumVauleClass { EVC1("No.1") { public String getName() { return "I'm "+EVC1.name; } }; private String name; private EnumVauleClass(String name) { this.name=name; } public String getName() { return name; } public static void main(String[] args) { EnumVauleClass evc1=EnumVauleClass.EVC1; out.println(evc1.getName()); } } [list=1]若你对2-8行的代码感到有问题,这是自然的! 我们在枚举里面好像定义了一个内部类似的,但是这个叫做“值”类,这是我的讲 法。真正的名称“值限定”类。再看看结果并不是No.1,而是I'mNo.1,证明这里是覆盖 了“父类”的方法getName():String,嗯?其实我个人认为,SUN的做法是把全面面 向对象发挥到个个方面。不多说了,最后我还告诉大家一个秘密,呵呵! 其实,我们说有的枚举都继承了java.lang.Enum类,前面说它不能继承的吗? 呵呵,你看看你的定义的枚举中,一定继承有Enum中的可继承的方法。 (下一章:ForEach语句) |
一共有 -2 条评论