------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、枚举类的概念
在某些情况下,一个类的对象时有限而且固定的,比如季节类,它只有4个对象;再比如行星类,目前只有9个对象。这种实例有限而且固定的类,在Java里被成为枚举类。
Java5新增了一个enum关键字(它与class、interface关键字的地位相同),用以定义枚举类。枚举类是一种特殊的类,它一样可以有自己的Field、方法,可以实现一个或者多个接口,也可以定义自己的构造器。
但枚举类终究不是普通类,它与普通类有如下简单区别:
——>枚举类可以实现一个或多个接口,使用enum定义的枚举类默认继承了java.lang.Enum类,而不是继承Object类。其中
java.lang.Enum类实现了java.lang.Serializable和java.lang.Comparable两个接口。
——>使用enum定义、非抽象的枚举类默认会使用final修饰,因此枚举类不能派生子类。
——>枚举类的构造器只能使用private访问控制符,如果省略了构造器的访问控制符,则默认使用private修饰;如果强制指定访
问控制符,则只能指定private修饰符。
——>枚举类的所有实例必须在枚举类的第一行显示列出,否则这个枚举类永远不能产生实例。列出这些实例时,系统会自动添
加public static final修饰,无须程序员显示添加。
所有的枚举类都提供了一个values方法,该方法可以很方便地遍历所有的枚举值。
下面程序定义了一个Season枚举类:
public enum Season {
//在第一行列出4个枚举实例
SPRING,SUMMER,FALL,WINTER;
}
定义枚举类时,需要显示列出所有的枚举值,如上面的SPRING,SUMMER,FALL,WINTER;所有的枚举值之间以英文逗号(,)隔开,枚举值列举结束后以英文分号作为结束。这些枚举值代表了该枚举类的所有可能实例。
如果需要使用该枚举类的某个实例,则可以使用EnumClass.variable的形式,如Season.SPRING。
package cai.test;
public class EnumTest {
public static void judge(SeasonEnum s){
switch(s){
case SPRING:
System.out.println("春暖花开,正好踏青");
break;
case SUMMER:
System.out.println("夏日炎炎,适合游泳");
break;
case FALL:
System.out.println("秋高气爽,进补及时");
break;
case WINTER:
System.out.println("秋冬雪飘,围炉赏雪");
break;
}
}
public static void main(String[] args){
for(SeasonEnum s : SeasonEnum.values()){
System.out.println(s);
}
for(SeasonEnum s : SeasonEnum.values()){
judge(s);
}
judge(SeasonEnum.FALL);
}
}
上面程序测试了Season枚举类的用法,该类通过values()方法返回了Season枚举类的所有实例,并通过循环迭代输出了Season枚举类的所有实例。
不仅如此,上面程序的switch表达式中还使用了Season对象作为表达式,这是JDK1.5增加枚举后对switch的扩展:switch的控制表达式可以是任何枚举类型。不仅如此,当switch控制表达式使用枚举类型时,后面case表达式中的值直接使用了枚举值的名字,无需添加枚举类作为限定。
所有的枚举类都继承了java.lang.Enum类,所有枚举类可以直接使用java.lang.Enum类中所包含的方法。java.lang.Enum类中提供了如下几个方法。
int compareTo(E o):该方法用于与指定枚举对象比较顺序。
String name():返回此枚举实例的名称。
int oridinal():返回枚举值在枚举类中的索引。
String toString():返回枚举常量的名称,与name方法相似,但toString()方法更常用。
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name):这是一个静态方法,用于返回指定枚举类中指定名称的枚举值。
二、枚举类的Field、方法和构造器
枚举类也是一种类,只是它是一种比较特殊的类,因此它一样可以定义Field、方法。下面程序定义一个Gender枚举类,该枚举类里包含了一个name实例变量。
public enum Gender {
MALE("男"),FEMALE;
//public String name;
private String name;
private Gender(){}
private Gender(String name){
this.name = name;
}
public void setName(String name){
switch(this){
case MALE:
if(name.equals("男")){
this.name = name;
}else{
System.out.println("参数错误");
return;
}
break;
case FEMALE:
if(name.equals("女")){
this.name = name;
}else{
System.out.println("参数错误");
return;
}
break;
}
}
public String getName(){
return this.name;
}
}
由上面这个程序可以知道,枚举类和普通类没有太大差别,只是枚举类一开始便要列出所有的枚举实例,列出枚举实例时不需使用new关键字,也无须显示调用构造器。如果要传参数,则像调用构造器一样即可。
三、实现接口的枚举类。
枚举类也可以实现一个或多个接口。与普通类实现一个或多个接口完全一样,枚举类实现一个或多个接口时,也需要实现该接口所包含的方法。如下面程序:
定义一个GenderDesc接口:
public interface GenderDesc {
void info();
}
下面是枚举类Gender实现接口的代码:
public enum GenderImpl implements GenderDesc{
//其他部分与上面Gender类的程序一样
@Override
public void info() {
System.out.println("这是一个用于定义性别Field的枚举类");
}
}
如果由枚举类来实现接口里的方法,则每个枚举值在调用该方法是都有相同的行为方式。如果需要每个枚举值在调用该方法时呈现出不同的行为方式,则可以让每个枚举值分别来实现该方法,如下程序:
public enum GenderImpl implements GenderDesc{
MALE("男")
{
public void info(){
System.out.println(this+"的方法");
}
},
FEMALE("女")
{
public void info(){
System.out.println(this+"的方法");
}
};
private String name;
private GenderImpl(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
并不是所有的枚举类都使用了final修饰!非抽象的枚举类才默认使用final修饰。对于一个抽象的枚举类而言——只要它包含了抽象方法,它就是抽象枚举类,系统会默认使用abstract修饰,而不是使用final修饰。
四、包含抽象方法的枚举类。
如果让枚举实例实现抽象枚举类的方法,该枚举实例实际是该枚举类子类的实例,如下程序:
public enum Operation2 {
PLUS{
public double eval(double x,double y){
return x+y;
}
},
MINUS{
public double eval(double x,double y){
return x-y;
}
},
TIMES{
public double eval(double x,double y){
return x*y;
}
},
DIVIDE{
public double eval(double x,double y){
return x/y;
}
};
public abstract double eval(double x,double y);
public static void main(String[] args){
System.out.println(Operation.PLUS.eval(5, 4));
System.out.println(Operation.MINUS.eval(5, 4));
System.out.println(Operation.TIMES.eval(5, 4));
System.out.println(Operation.DIVIDS.eval(5, 4));
}
}
枚举类里定义抽象方法时不能使用abstract关键字将枚举类定义成抽象类,但因为枚举类需要显示创建枚举值,而不是作为父类,所有定义每个枚举值时必须为抽象方法提供实现,否则将出现编译错误。