1.为什么要有枚举?
有些具实际意义的变量,它的取值是固定的,只有那么几个值,出现其他值就违背了对象本身的现实意义。
比如性别只有男和女,两个值其他值就是错误的。又如交通信号灯只有红绿黄三种颜色。这个时候我们就需要用到枚举了。
枚举就是要让个类型的变量的取值只能为若干个固定的值中的一个,否则,编译器就会报错。
枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现的这一目标。
注意:类集框架中提到了用来输出Vector的枚举Enumeration,Enumeration类似于迭代器与用enum定义的枚举类是不一样的
2.用普通类实现枚举功能
步骤:
1)私有化构造方法,控制对象的个数,只允许使用内部提供的对象
2)每个元素分别用一个公有的静态成员变量表示
3)可以有若干共有方法或抽象方法。例如:如果用Weekday类实现枚举要提供的nextDay方法必须是抽象的,
采用抽象方法定义nextDay就将大量的ifelse语句转移成了一个个独立的类。
示例代码:
public abstract class Weekday {
public final static Weekday SUN = new Weekday(){
public Weekday nextDay() {
return MON;
}
};
public final static Weekday MON = new Weekday(){
public Weekday nextDay() {
return SUN;
}
};
private Weekday(){}
public abstract Weekday nextDay();
public String toString(){
return this == MON?"MON":"SUN";
}
}
3.枚举的基本应用
1)枚举类通过关键字enum定义,是一种特殊的类,其中的每个元素都是该类的一个静态实例对象,
更确切的说是匿名内部类的子类对象向上转型。
2)多个枚举常量常以逗号隔开,结尾分号可以不写,变量名通常大写
3)枚举常量调用重写后的toString方法,默认返回与变量名相同的字符串
4)所有通过enum关键字定义的枚举类都默认继承Enum类
示例代码:
public enum WeekDay1 {
SUN, MON, TUE, WED, THU, FRI, SAT
}
所有通过enum关键字定义的枚举类都默认继承Enum类,继承了Enum类的所有非私有方法
常用的非静态方法:
String name(); 返回该枚举常量的名称
int ordinal(); 返回枚举常量的序数,即它在枚举声明中的位置,其中初始常量序数为零
String toString(); 返回该枚举常量的名称
Class getClass(); 返回该类的Class对象
静态方法:
T valueOf(String str); 返回该字符串对应的枚举常量对象
T[] values(); 返回包含所有枚举常量对象的数组
示例代码:
public enum WeekDay1 {
SUN, MON, TUE, WED, THU, FRI, SAT;
public static void main(String[] args) {
WeekDay1 SUN = WeekDay1.SUN;
//获得SUN对象的名称
System.out.println(SUN.name());
//获得SUN对象在枚举类中的序数
System.out.println(SUN.ordinal());
//通过字符串MON获得枚举常量MON对象
WeekDay1 MON = WeekDay1.valueOf("MON");
System.out.println(MON.toString());
//获得WeekDay1中的所有枚举常量对象
WeekDay1[] arr = WeekDay1.values();
for(int i=0; i<arr.length; i++)
System.out.println(arr[i].toString());
}
}
4.枚举的高级应用
1)枚举就相当于一个类,其中也可以定义构造方法、成员变量、普通方法和抽象方法
2)枚举元素必须位于枚举体最开始部分, 枚举元素列表的后要有分号与其他成员隔开。
把枚举中的成员方法或变量等放在枚举元素的前面,编译器报告错误。
带构造方法的枚举
① 构造方法必须定义成私有的
②如果有多个构造方法,按照传入的参数选择对应的构造函数
③枚举元素MON和MON()的效果是一样的,都是调用默认的构造的方法
④枚举常量使用之前会调用相应的构造方法来为所有的常量初始化
示例代码:
public enum TrafficLamp {
RED(5), GREEN, YELLOW; //枚举列表
int time; //时间
//默认的构造方法
private TrafficLamp(){
System.out.println("first-----");
}
//设置时间的构造方法
private TrafficLamp(int time){
System.out.println("second-----");
this.time = time;
}
}
运行截图:
由运行结果可知,枚举类使用之前会分别调用对应的构造方法为每一个枚举对象初始化
带方法的枚举
以上面的交通灯为例,实现抽象的next方法,每个元素分别是由枚举类的子类来生成的实例对象,这些子类采用类似内部类都方法进行定义
示例代码:
public enum TrafficLamp {
RED(5){
@Override
public TrafficLamp next() {
return GREEN;
}
},
GREEN(30){
@Override
public TrafficLamp next() {
return YELLOW;
}
},
YELLOW(5){
@Override
public TrafficLamp next() {
return RED;
}
}; //枚举列表
int time; //时间
//默认的构造方法
private TrafficLamp(){
System.out.println("first-----");
}
//设置时间的构造方法
private TrafficLamp(int time){
System.out.println("second-----");
this.time = time;
}
public abstract TrafficLamp next();
}
注:枚举只有一个成员时,就可以做一种单例的实现方式
5.用于switch语句
JDK1.6switch语句支持enum类型,使用枚举,能让我们的代码可读性更强。
示例代码:
public class Demo {
static void show(TrafficLamp tl){
switch(tl){
case RED: System.out.println("红灯来了!");break;
case GREEN: System.out.println("绿灯来了!");break;
case YELLOW:System.out.println("现在是黄灯!");break;
}
}
public static void main(String[] args) {
show(TrafficLamp.GREEN);
}
}