概念 enum 是在 JDK 1.5 版本才引入的新特性。在 Java 中,被 enum 关键字修饰的类型就是枚举类型:
1 2 3 enum Weekday { MON, TUE, WED, THU, FRI, SAT, SUN }
声明为 Weekday 类型的变量,只能存储这个枚举类型声明中给定的某个枚举值,或者 null 值,null 表示这个变量没有设置任何值。
注意:在定义枚举类型时,我们所使用的关键字是 enum,用法与 class 关键字类似,只不过前者定义枚举类型,后者是定义类。 枚举值一般都是大写的字母,任意两个枚举成员不能具有相同的名称,且它的常数值必须在该枚举的基础类型的范围之内,多个枚举成员之间使用逗号分隔。
本质 尽管 enum 看起来像是一种新的数据类型,事实上,enum 的本质是一种受限制的类,并且具有自己的方法,这些后面再细说。
在使用关键字 enum 创建枚举类型并编译后,编译器会为你生成一个相关的类,这个类继承自 java.lang.Enum 类:
1 2 public abstract class Enum <E extends Enum <E >> implements Comparable <E >, Serializable { ... }
让我们看看反编译 Weekday.class 之后的结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public final class WeekDay extends Enum { public static WeekDay[] values() { return (WeekDay[])$VALUES.clone(); } public static WeekDay valueOf (String name) { return (WeekDay)Enum.valueOf(problems/enumeration/WeekDay, name); } private WeekDay (String s, int i) { super (s, i); } public static final WeekDay MON; public static final WeekDay TUE; public static final WeekDay WED; public static final WeekDay THU; public static final WeekDay FRI; public static final WeekDay SAT; public static final WeekDay SUN; private static final WeekDay $VALUES[]; static { MON = new WeekDay("MON" , 0 ); TUE = new WeekDay("TUE" , 1 ); WED = new WeekDay("WED" , 2 ); THU = new WeekDay("THU" , 3 ); FRI = new WeekDay("FRI" , 4 ); SAT = new WeekDay("SAT" , 5 ); SUN = new WeekDay("SUN" , 6 ); $VALUES = (new WeekDay[] { MON, TUE, WED, THU, FRI, SAT, SUN }); } }
从反编译的代码可以看出编译器确实帮助我们生成了一个 Weekday 类,它继承自 java.lang.Enum 抽象类,并且该类是 final 修饰的,将无法被继承。
除此之外,编译器还帮我们生成了七个 Weekday 类型的静态常量,分别对应枚举中定义的七个日期,这也充分说明了当我们定义一个枚举类型时,每一个枚举类型成员都可以看作是 Enum 类的实例,这些枚举成员默认都被 public static final 进行修饰,当使用枚举类型成员时,直接使用枚举名称调用成员即可。
注意编译器还为我们生成了两个静态方法,分别是 values() 和 valueOf(),前者返回我们定义的所有枚举成员,后者可以可以按照枚举成员名称获取对应的枚举值。
java.lang.Enum 类方法 Enum 类是所有 Java 语言枚举类型的公共基类(注意 Enum 是抽象类),以下是它的常见方法:
1 2 3 4 5 6 7 8 9 10 11 public final int compareTo (E o) {} public final boolean equals (Object other) {} public final Class<E> getDeclaringClass () {} public final String name () {} public final int ordinal () {} public String toString () {}
未完待续。