定义
在某些情况下,一个类的对象是有限而且固定的,比如季节类,它只有4个对象;再比如行星类,目前只有8个对象。这种实例有限而且固定的类,在Java里被称为枚举类。
Java5新增一个enum关键字(它与class,interface关键字的地位相同),用以定义枚举类。枚举类是一个特殊的类,它一样可以有自己的成员变量、方法,可以实现一个或者多个接口,也可以定义自己的构造器。一个java源文件中最多只能定义一个public访问权限的枚举类,且该Java源文件也必须和该枚举类的类名相同。
枚举类和普通类有如下区别
- 枚举类可以实现一个或者多个接口,使用enum定义的枚举类默认继承了java.lang.Enum类,而不是默认继承Object类,因此枚举类不能显示继承其他父类。其中java.lang.Enum 类实现了java.lang.Serializable和java.lang.Comparable两个接口。
- 使用enum 定义、非抽象的枚举类默认会使用final修饰,因此枚举类不能派生子类。
- 枚举类的构造器只能使用private访问控制符,如果省略了构造器的访问控制符,则默认使用private修饰;如果强制指定访问控制符,则只能指定private修饰符
- 枚举类的所有实例必须在枚举类的第一行显示列出,否则这个枚举类永远都不能产生实例。列出这些实例时,系统会自动添加public static final修饰,无序程序员显示添加。
定义枚举类是,需要显式列出所有的枚举值,如下面代码实例所示,所以的枚举值时间以英文逗号(,)隔开,枚举值列举结束后以英文分号作为结束。这些枚举值代表了该枚举类的所有可能的实例。
public enum SeasonEnum {
//在第一行列出4个枚举实例
SPRING,SUMMER,FALL,WINTER
}
枚举类实例
EnumTest
public class EnumTest {
public 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);
}
new EnumTest().judge(SeasonEnum.SPRING);
}
}
运行结果
枚举类的成员变量、方法和构造器
实例变量
Gender
public enum Gender {
MALE,FEMALE;
//定义一个public修饰的实例变量
public String name;
}
GenderTest
public class GenderTest {
public static void main(String[] args) {
Gender gender = Enum.valueOf(Gender.class, "FEMALE");
gender.name="女";
System.out.println(gender+"代表"+gender.name);
}
}
运行结果
枚举类的实例只能是枚举值,而不是随意地通过new来创建枚举类对象。
Java应该把所以设计成良好封装的类,所以不应该允许直接访问Gender类的name成员变量,而是应该通过方法来控制对name的访问。否则可能出现很混乱的情形。
对上面代码进行改进
Gender
public enum Gender {
MALE("男"),FEMALE("女");
private final String name;
Gender(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
GenderTest
public class GenderTest {
public static void main(String[] args) {
System.out.println(Gender.FEMALE.getName());
}
}
运行结果
实现接口的枚举类
枚举类也可以实现一个或多个接口。
代码举例说明
GenderDesc
public interface GenderDesc {
void info();
}
Gender
public enum Gender implements GenderDesc {
MALE("男"){
@Override
public void info() {
System.out.println("这个枚举值代表男性!");
}
},
FENALW("女"){
@Override
public void info() {
System.out.println("这个枚举值代表女性!");
}
};
Gender(String name) {
this.name = name;
}
private final String name;
public String getName() {
return name;
}
public static void main(String[] args) {
Gender.FENALW.info();
}
}
运行结果
包含抽象方法的枚举类
演示代码
Operation
public enum Operation {
PLUS {
@Override
public double eval(double x, double y) {
return x + y;
}
},
MINUS {
@Override
public double eval(double x, double y) {
return x - y;
}
},
TIMES {
@Override
public double eval(double x, double y) {
return x * y;
}
},
DIVIDE {
@Override
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(3, 4));
System.out.println(Operation.MINUS.eval(4, 1));
System.out.println(Operation.TIMES.eval(3, 4));
System.out.println(Operation.DIVIDE.eval(4, 2));
}
}
运行结果
说明:枚举类里定义抽象方法时不能使用abstract关键字将枚举类定义成抽象类(因为系统自动会为它添加abstract关键字),但因为枚举类需要显示创建枚举值,而不是作为父类,所以定义的每个枚举值时必须为抽象方法提供实现,否则出现编译错误。