Java中的枚举有点复杂,不同于C++中的enum。因为在java中enum被看作一个特殊的类,其中每一个元素都是该类的一个实例对象。
用一个普通类模拟enum:
私有构造方法,每一个元素分别用一个public static final修饰,将元素这间特有的方法抽象化,以内部类的形式定义,如下nextDay方法。
abstract class WeekDay {
private WeekDay(){}
public static final WeekDay MON = new WeekDay(){
public WeekDay nextDay() {
return TUE;
};
};
public static final WeekDay TUE = new WeekDay(){
public WeekDay nextDay() {
return WEDN;
};
};
public static final WeekDay WEDN = new WeekDay(){
public WeekDay nextDay() {
return THI;
};
};
public static final WeekDay THI = new WeekDay(){
public WeekDay nextDay() {
return FRI;
};
};
public static final WeekDay FRI = new WeekDay(){
public WeekDay nextDay() {
return SAT;
};
};
public static final WeekDay SAT = new WeekDay(){
public WeekDay nextDay() {
return SUN;
};
};
public static final WeekDay SUN = new WeekDay(){
public WeekDay nextDay() {
return MON;
};
};
public abstract WeekDay nextDay();
}
一个java枚举使用enum代替class定义。自定义enum的基类是Java中的一个名为Enum的抽象类,也就是首字母大写。原型如下:
public abstract class Enum<E extends Enum<E>>extends Objectimplements Comparable<E>, Serializable
可以看出Enum本身就是extends自Object的,所以Java中的枚举完全可以看作是一个类,其实它就是一个类,只是不能被实例化。所以它除了从Object继承来的一些方法外,另外提供了一些用于特定的方法。
public final int compareTo(E o) //比如两个枚举的顺序
public final int ordinal() //返回枚举在序列中的位置,默认从0开始
public final String name() //返回枚举在序列中的名字
//返回带指定名称的指定枚举类型的枚举常量
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
枚举元素必须定义在第一行,如果枚举定义了构造函数,那么可以在申请元素的时候为其显示的指定构造函数,如:
enum WeekDay {
SUN(1),MON(2),TUE,WED,THI,FRI,SAT;
WeekDay(){}
int num = 0;
WeekDay(int num){
this.num = num;
}
}
因为枚举也是一个类,所以同样遵守构造函数的特性,默认调用无参构造。枚举不能extends任何类因为它本身强制默认继承自Enum类,也不能派生任何类,但却可以implements一个interfce。如果在枚举内没有具体实现接口中所有的抽象方法,那么在枚举第一行申请枚举元素时,必须为每一个元素使用内部类的方法具体化接口的抽象函数。如:
interface Test {
void func();
}
enum WeekDay2 implements Test{
SUN(){public void func() {}},
MON(){public void func() {}};
}
也就是说Java中的枚举,不单拥有自己所在enum中的序列,而且还可以为每一个枚举元素定义特有的功能方法。调用枚举元素时可以像使用对象一样方便的操作他们的额外功能,甚至可以在实现这些抽象方法内执行计算操作,逻辑操作。不再是单一的序列功能。
除了流体系外枚举是我在Java中见过的第二个很实用的功能,Java枚举的功能扩展性比C++枚举要多很多,虽然说同样的功能实现它绝对不成问题,但免不了要多费一些手脚了,只是这样定义枚举会不会又是一种资源浪费呢。要知道在C++中enum仅仅只是常量,所占用的内存空间是非常少的,可以方便的用来代表一些同类序的数列,这也是enum在C++中存在至今的关键原因,Java中的enum完全颠覆了这一原则,如果仅仅只是想要一个常量序列,那么在Java中使用枚举好像并不是很好的选择。
由于枚举无法被实例化,只能在enum内部和一行定义他的元素。即每一个元素代表一个枚举的实例对象,那么当一个枚举只有一个元素存在时,也就是说该枚举自始至终都只有一个实例对象,可以用来当做单例设计模式中的另一种定义方法。