原创

【每天十分钟JAVA快速入门】(二十)枚举

枚举(enum)

我们常常会使用到一些属于相同类型且数量或取值范围有限的变量,例如衣服的尺码,一年的十二个月,一周的七天,任务处理的状态等等。在不使用枚举的情况下,一般会将它们定义为一系列的常量,但是这样使用可能会有一些安全隐患,即使在设置了非法的值时编译器也不会给出任何警告。

定义
使用enum关键字来定义一个枚举类型,和定义常量类似,推荐使用大写的命名方式来命名枚举值,多个枚举值之间以逗号分开,例如经典的一周七天:
public enum Week {
MONDAY, TUESDAY, WEDNESDAY,THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

Enum类
Enum类是Java枚举类的基类,实际上我们使用enum定义了一个枚举类型时,编译器会自动生成一个继承了Enum的类(因此enum定义的枚举是不能继承的),例如上面的Week枚举,编译器会生成一个继承了Enum的Week类,同时实例化7个该类的static final对象对应每一个枚举值。Enum类的常用方法如下:
方法
返回类型
说明
equals(Object other)
boolean
比较两个枚举值是否相等
ordinal()
int
返回枚举常量的序数(在枚举声明中的位置,从0开始)
compareTo(E o)
int
比较两个枚举值的顺序,就是比较ordinal
getDeclaringClass()
Class<?>
返回枚举类型相对应的Class对象
name()
String
返回枚举值的名称
toString()
String
返回枚举值的名称
static valueOf(Class<T> enumType, String name)
static<T extends Enum<T>> T
返回指定名称和类型的枚举值

运行下面的代码,快速了解一下上面的方法:
Week monday = Week.MONDAY;
Week tuesday = Week.TUESDAY;
System.out.println(monday.equals(tuesday));
System.out.println(monday.ordinal());
System.out.println(tuesday.ordinal());
System.out.println(monday.compareTo(tuesday));
System.out.println(monday.getDeclaringClass());
System.out.println(monday.name());
System.out.println(tuesday.name());
System.out.println(monday.toString());
System.out.println(tuesday.toString());
System.out.println(Enum.valueOf(Week.class,"MONDAY"));
System.out.println(Enum.valueOf(Week.class,"TUESDAY"));

编译器还会为声明的枚举类生成一个静态的方法values,返回该枚举类型的所有枚举值,但Enum类本身没有这个方法,例如:
Week[] days = Week.values();
for(Week day : days){
System.out.println(day);
}
Enum类的构造器如下,但是只能由编译器调用,在实例化枚举值对象时默认使用name和ordinal来构造,枚举不能够通过反射来实例化。
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}

枚举方法
枚举里可以定义方法和自定义构造器,但是必须在枚举实例定义完之后,枚举实例定义最后以分号结尾。但是即使是自定义构造器仍然只能由编译器调用,例如上面的Week我们需要实例化带中文描述的枚举实例:
public enum Week {
MONDAY("周一"),
TUESDAY("周二"),
WEDNESDAY("周三"),
THURSDAY("周四"),
FRIDAY("周五"),
SATURDAY("周六"),
SUNDAY("周日");

private String chineseName;
public String getChineseName() {
return chineseName;
}
public void setChineseName(String chineseName) {
this.chineseName = chineseName;
}

Week(String chineseName) {
this.chineseName = chineseName;
}
}
打印出中英文对照:
Week[] days = Week.values();
for(Week day : days){
System.out.println(day + ":" +day.getChineseName());
}
当然我们也可以通过覆盖toString方法来打印出中英文对照:
@Override
public String toString() {
return super.toString() + ":" + chineseName;
}
Week[] days = Week.values();
for(Week day : days){
System.out.println(day.toString());
}
实际上也只有这个方法可以覆盖,因为Enum类的其它方法都是final的。

枚举还可以定义抽象方法,每个枚举实例需要各自实现该方法,例如定义一个抽象方法 isWorkingDay,周一到周五返回true,周六和周日返回false:
public enum Week {
MONDAY("周一"){
@Override
public boolean isWorkingDay() {
return true;
}
},
TUESDAY("周二"){
@Override
public boolean isWorkingDay() {
return true;
}
},
WEDNESDAY("周三"){
@Override
public boolean isWorkingDay() {
return true;
}
},
THURSDAY("周四"){
@Override
public boolean isWorkingDay() {
return true;
}
},
FRIDAY("周五"){
@Override
public boolean isWorkingDay() {
return true;
}
},
SATURDAY("周六"){
@Override
public boolean isWorkingDay() {
return false;
}
},
SUNDAY("周日"){
@Override
public boolean isWorkingDay() {
return false;
}
};

private String chineseName;

Week(String chineseName) {
this.chineseName = chineseName;
}

@Override
public String toString() {
return super.toString() + ":" + chineseName + ":is working day:" + this.isWorkingDay();
}

public abstract boolean isWorkingDay();
}
这样通过调用新的toString方法就可以打印出是否是工作日了。


正文到此结束