敏捷冲冲_

The Art of software design

Java 枚举(Enum)类型详解

概念

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){} // 当指定对象等于此枚举常量时,返回 true

public final Class<E> getDeclaringClass(){} // 返回与此枚举常量的枚举类型相对应的 Class 对象

public final String name(){} // 返回此枚举常量的名称,在其枚举声明中对其进行声明

public final int ordinal(){} // 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)

public String toString(){} // 返回枚举常量的名称,它包含在声明中

未完待续。