------- android培训、java培训、期待与您交流! ----------
枚举:
枚举让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。
枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。
枚举类只有几种特定的值,并且会在编译期间就检查,避免非法值。
比如:对于星期天的值,不同的人理解不是同的,可能在赋值的过程中赋了不同的值,而编译器只检查语法而无法提示出来,那么等程序运行的时候就可以出现错误!
所以,枚举就出现了。它实现了让某个类型的变量的取值只能是若干个固定值中的一个,否则在编译期间编译器就会报错,提高了程序运行的安全性。
参考:EnumTest.java,WeekDay.java
使用普通的java类来实现枚举类,可以帮助理解:
1.私有化构造方法并定义两个或多个全局对象;
即:private WeekDay(){}
public final static WeekDay SUN = new WeekDay();
public final static WeekDay SAT = new WeekDay();
再调用该类的对象时,只能是WeekDay weekDay = WeekDay.SUN;
此时常量SUN、SAT其实就是WeekDay的一个对象。
public WeekDay nextDay(){
if(this == SUN){
return MON;
}else{
return SUN;
}
}
public String toString(){
return this == SUN?"SUN":"MON";
}
我们可以将nextDay()方法抽象化,让子类来复写。
---------------------------------------------------------------------
public abstract WeekDay nextDay();----
public final static WeekDay SUN = new WeekDay(){
public WeekDay nextDay(){
return MON;
}
}
注意:此时每一个枚举常量其实就是该类的匿名内部类对象了。
使用普通类来模拟一个枚举类,总结:
第一步:私有的构造方法
第二步:每个元素分别用一个公有的静态成员变量表示
第三步:可以有若干公有方法或抽象方法。该例子:采用抽象方法定义nextDay就将大量的if.else语句转移成了一个个独立匿名内部类。
即:在模拟的内部类中定义几个匿名内部类。
在枚举内中定义几个抽象方法,由子类实现
public final static WeekDay SUN = new WeekDay(){子类的实现方式};
public final static WeekDay SAT= new WeekDay(){子类的实现的方式};
所以枚举中的成员常量实际上是该枚举类的匿名内部类对象。
---------------------------------------------------------------------------
思考:如何定义一个枚举类呢?
main(){
WeekDay weekDay2 = WeekDay.FRI;
System.out.println(weekDay2);
System.out.println(weekDay2.name());//
System.out.println(weekDay2.ordinal());
System.out.println(WeekDay.valueOf("SUN")); //返回带指定名称的指定枚举类型的枚举常量。
System.out.println(WeekDay.values().length); //吧所有的元素转换成数组,以便操作
}
public enum WeekDay(){
SUN,MON,TUE,WED,THI,FRI,SAT
}
-------------------------------------------------------
思考2:实现带有构造方法的枚举
注意: 1.构造方法必须位于元素列表之后。
2.构造方法必须私有化;
3.还可以定义带参数的构造方法;
4.当类中存在多个构造方法时,
在枚举中定义构造方法,必须被私有化并定义在常量后面。
成员常量可以通过传递数字来指定调用那个构造方法。
public enum WeekDay{
SUN,MON,TUE,WED,THI,FRI,SAT;
private WeekDay(){System.out.println("first");}//空参数的构造方法
private WeekDay(int day){System.out.println("second");}//带参数的构造方法
只要用到该类的静态成员,那么静态成员初始化时会默认调用构造方法。
如果在获取枚举常量时,要指定调用哪个构造方法,可以在静态常量后面+(实际参数或者不加实际参数),比如:SUN(1),MON()默认会调用有参数的构造方法;
}
----------------------------------------------------------------------------------------------------------------------------------
思考3:实现带有抽象方法的枚举(做一个交通灯)
public enum TrafficLamp{
RED(30){
public TrafficLamp nextLamp(){ //子类复写
return GREEN;
}
},
GREEN(45){
public TrafficLamp nextLamp(){
return YELLOW;
}
},
YELLOW(5){
public TrafficLamp(){
return RED;
}
};
public abstract TrafficLamp nextLamp();//父类的抽象方法
private int time;//时间属性
private TrafficLamp(int time){
this.time = time;
}
}
public enum TrafficLamp{
RED(30)/*小括号内有无参数可以指定构造方法*/{子类复写抽象方法
},
GREEN(45){子类复写抽象方法
},
YELLOW(5){子类复写抽象方法
};
public abstract TrafficLamp nextLamp();//注意返回的仍然是枚举类对象!绝!
private int time;
private TrafficLamp(int time){this.time = time}
注意:普通类的对象在创建时,可以调用该类的有参数的构造方法,如new Date(300){};
}
注意:RED(30)/*小括号内有无参数可以指定构造方法*/{子类复写抽象方法
},表示:用静态全局常量RED引用该类的实体对象,该对象通过调用父类的有参的构造方法。