最近项目中又用到了枚举类型,结果还是摆脱不了google查资料的境地,用一次查一次,也慢慢失去了对自己记忆力的自信,看来还是稍微记一下的好。
一、什么是枚举
枚举是 java5中新加的一种类型,但是我们并不陌生,因为在其它语言中早已存在。说白了就是预先定义一组常量,并作为一个新的类型,而这种新类型的取值范围是确定了的,只能在这组常量里面。
什么时候使用枚举呢?一个最重要的依据是取值范围,一个用枚举表示的对象,在你的项目或系统里 的取值范围应该是确定的,不变的。最著名的例子莫过天用于表示星期几。
二、如何定义
很简单,在大括号里罗列它的值就可以了。
一个表示星期几的枚举类:
- public enum Week {
- SUNDAY,
- MONDAY,
- TUESDAY,
- WEDNESDAY,
- THURSDAY,
- FRIDAY,
- SATURDAY;
- }
public enum Week {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY;
}
三、用枚举的好处
我认为首先它表义,和现实逻辑更接近。从编程上来说,它使我们程序更简单了。
在java中,枚举出现以前,我们大多数是用静态变量来实现类似功能的。如:
- public class StaticWeek {
- public static final int SUNDAY = 0;
- public static final int MONDAY = 1;
- public static final int TUESDAY = 2;
- public static final int WEDNESDAY = 3;
- public static final int THURSDAY = 4;
- public static final int FRIDAY = 5;
- public static final int SATURDAY = 6;
- }
public class StaticWeek {
public static final int SUNDAY = 0;
public static final int MONDAY = 1;
public static final int TUESDAY = 2;
public static final int WEDNESDAY = 3;
public static final int THURSDAY = 4;
public static final int FRIDAY = 5;
public static final int SATURDAY = 6;
}
在上面的描述中,我们用StaticWeek.MONDAY 来表示星期一,但这是一种假象,是我们程序人员对自己的一种自我催眠。对于java虚拟机而言它还是int型,和int 1 没区别。
比如有一个类它有一个私有变量dayOfWeek表示星期几:
- private int dayOfWeek = StaticWeek.SUNDAY;
- private Week dayOfWeek2 = Week.SUNDAY;
- public void setDayOfWeek(int dayOfWeek) {
- this.dayOfWeek = dayOfWeek;
- }
private int dayOfWeek = StaticWeek.SUNDAY;
private Week dayOfWeek2 = Week.SUNDAY;
public void setDayOfWeek(int dayOfWeek) {
this.dayOfWeek = dayOfWeek;
}
- 这个变量有一个初始值StaticWeek.SUNDAY,但是它和int 0 没区别,只是我们为了程序好理解,人为作的一种规则,当然这种规则也给我们带来了很大的方便。
- 它还有一个set方法,但它的参数类型是int型,所以它参数值并未局限于我们定义的七种静态量。所以你给它一个8,它也不会拒绝,但这显然也是不合我们定义的逻辑的,所以我们还要验证参数值是否合法。这里很不方便,如果传入的参数一定是合法的该有多好啊,如果接收的参数只能是我定义的七种值就妙不可言了!
- myObj.setDayOfWeek(StaticWeek.FRIDAY);//我们都人为希望大家都这样写,但这需要人的自觉
- myObj.setDayOfWeek(1);//功能同上
- myObj.setDayOfWeek(8);//并未杜绝这种情况的调用,实际上是不合法
myObj.setDayOfWeek(StaticWeek.FRIDAY);//我们都人为希望大家都这样写,但这需要人的自觉
myObj.setDayOfWeek(1);//功能同上
myObj.setDayOfWeek(8);//并未杜绝这种情况的调用,实际上是不合法
用枚举来实现上面类似的功能:
- private Week dayOfWeek2 = Week.SUNDAY;
- public void setDayOfWeek2(Week dayOfWeek2) {
- this.dayOfWeek2 = dayOfWeek2;
- }
private Week dayOfWeek2 = Week.SUNDAY;
public void setDayOfWeek2(Week dayOfWeek2) {
this.dayOfWeek2 = dayOfWeek2;
}
- myObj.setDayOfWeek2(Week.FRIDAY);
- //下面的调用是不合法,编译期就会报错,枚举限制了调用类型,只能是Week类型,这也确定了它的取值范围,而且保证是合法的
- myObj.setDayOfWeek2(otherType);
myObj.setDayOfWeek2(Week.FRIDAY);
//下面的调用是不合法,编译期就会报错,枚举限制了调用类型,只能是Week类型,这也确定了它的取值范围,而且保证是合法的
myObj.setDayOfWeek2(otherType);
- 首先我们看到我们定义的私有变量就是Week类型的,它是一种类型,而这种类型的取值范围是我们自己定义的 ,所以它怎么取值都不会跑出我们的手掌心,如果万一超出了,你可以去找Sun先生问一下,但首先一定要先确认不是自己的错。
- 再看方法,我们把参数类类型设置成了Week类型,这样就再也不会有人写出那种让人不理解的代码了(myObj.setDayOfWeek(8)) ,因为有Sun先生为你把关。
三、枚举使用举例
一般的使用可以参考上面,唯一值的注意的如何取得一个该类型的实例:类型前缀.要取的值
API:values() ,取得一个包括所有值的该枚举类型数组,如遍历一个枚举
- for(Week w:Week.values()){
- System.out.println(w);
- }
for(Week w:Week.values()){
System.out.println(w);
}
输出结果:
- SUNDAY
- MONDAY
- TUESDAY
- WEDNESDAY
- THURSDAY
- FRIDAY
- SATURDAY
SUNDAY
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
API:valueOf() ,取出一个枚举的一值
- System.out.println(Week.valueOf("MONDAY"));//同Week.MONDAY
System.out.println(Week.valueOf("MONDAY"));//同Week.MONDAY
API.Enum.valueOf(class,String) ,一个静态方法,取出某个枚举类型的某个值。
- System.out.println(Enum.valueOf(Week.class, "MONDAY"));//同上
System.out.println(Enum.valueOf(Week.class, "MONDAY"));//同上
基本上枚举就定义了上面三个方法,当然我们还可以编写自己的方法和自己的构造函数。
在switch中使用枚举
我们为那个有dayOfWeek2变量的类定义一个打印信息的方法
- public void printInfo(){
- String day;
- switch(this.dayOfWeek2){
- case SUNDAY:
- day = "星期天";
- break;
- case MONDAY:
- day = "星期一";
- break;
- case TUESDAY:
- day = "星期二";
- break;
- case WEDNESDAY:
- day = "星期三";
- break;
- case THURSDAY:
- day = "星期四";
- break;
- case FRIDAY:
- day = "星期五";
- break;
- case SATURDAY:
- day = "星期六";
- break;
- default:
- day = "星期几?";
- }
- System.out.println("我是"+day);
- }
public void printInfo(){
String day;
switch(this.dayOfWeek2){
case SUNDAY:
day = "星期天";
break;
case MONDAY:
day = "星期一";
break;
case TUESDAY:
day = "星期二";
break;
case WEDNESDAY:
day = "星期三";
break;
case THURSDAY:
day = "星期四";
break;
case FRIDAY:
day = "星期五";
break;
case SATURDAY:
day = "星期六";
break;
default:
day = "星期几?";
}
System.out.println("我是"+day);
}
- 注意,枚举在case字句中的情况,是不包括枚举类型的前缀的。
我们使用一下上面的方法:
- myObj.setDayOfWeek2(Week.FRIDAY);
- myObj.printInfo();
myObj.setDayOfWeek2(Week.FRIDAY);
myObj.printInfo();
输出结果:
- 我是星期五
我是星期五
自定义构造函数和自己的方法
改造Week:
- public enum Week {
- SUNDAY("日"),
- MONDAY("一"),
- TUESDAY("二"),
- WEDNESDAY("三"),
- THURSDAY("四"),
- FRIDAY("五"),
- SATURDAY("六");
- private String name;
- Week(String name){
- this.name = "星期"+name;
- }
- public String toString(){
- return this.name;
- }
- }
public enum Week {
SUNDAY("日"),
MONDAY("一"),
TUESDAY("二"),
WEDNESDAY("三"),
THURSDAY("四"),
FRIDAY("五"),
SATURDAY("六");
private String name;
Week(String name){
this.name = "星期"+name;
}
public String toString(){
return this.name;
}
}
如上,枚举类型可以自定义自己的构造函数,自己的私有变量,自己的方法,重写方法。
根据改造的类我们可以重写上面打印信息方法printInfo():
- public void printInfo2(){
- System.out.println("我是"+this.dayOfWeek2.toString());
- }
public void printInfo2(){
System.out.println("我是"+this.dayOfWeek2.toString());
}
枚举的构造函数
- 构造函数前面是不能有修饰符的,或者你只能写private,即不允许我们人为调用的
- 当定义一个枚举类型时,实际上已经确定了它的实例对象,如Week, 只有七个实例对象
- 实例对象的构造,也是我们预先定义好的,如Week.MONDAY对象,它的构造:MONDAY("一“),而括号里的字符串就是我们传到构造函数的参数。
- 何时构造,枚举类型的所有实例是一起构造的,当我们初次使用某个实例时。如:当我们第一次使用任何一个Week实例时,都会构造七个实例。
更改构造函数,增加一个输出
- Week(String name){
- System.out.println(name);//在初次使用时,所有值的构造会调一往遍
- this.name = "星期"+name;
- }
Week(String name){
System.out.println(name);//在初次使用时,所有值的构造会调一往遍
this.name = "星期"+name;
}
当我们第一次使用Week的实例时:
- System.out.println("3");
- myObj.setDayOfWeek2(Week.FRIDAY);
- System.out.println("4");
System.out.println("3");
myObj.setDayOfWeek2(Week.FRIDAY);
System.out.println("4");
输出结果
- 3
- 日
- 一
- 二
- 三
- 四
- 五
- 六
- 4
3
日
一
二
三
四
五
六
4
三、总结完毕
本文链接: http://kino.iteye.com/blog/204949 转载请注明出处,谢谢。