Java漫游笔记-02-07-枚举

本质

枚举是一种类
并且,所有的枚举类型都是 java.lang.Enum 的子类。

定义

下面演示如何定义一个枚举类型,它刚好有3个实例:

1
2
3
public enum State {
AVAILABLE, DISABLED, LOCKED
}

如果需要的话,还可以在枚举类型中添加一些属性、构造器和方法。
当然,构造器只是在构造枚举常量的时候被调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public enum State {
AVAILABLE("正常"), DISABLED("禁用"), LOCKED("锁定");

private final String description;

private State(String description) {
this.description = description;
}

public String getDescription() {
return this.description;
}

@Override
public String toString() {
return this.description;
}
}

基本用法

前面提到:所有的枚举类型都是 Enum 的子类。
因此,我们定义的枚举类型也很自然地继承了 Enum 类的一些方法。
其中比较常用的有:

  • toString() :默认返回枚举常量的名称。

    1
    2
    State state = State.AVAILABLE;
    state.toString(); // 返回 AVAILABLE
  • valueOf() :返回带指定名称的指定枚举类型的枚举常量。

    1
    State state = State.valueOf("AVAILABLE"); // 返回 State.AVAILABLE
  • ordinal() :返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为 0 )。

    1
    ing ordinalNumber = State.AVAILABLE.ordinal(); // 返回 0
  • name() :返回枚举常量的名称。

    1
    2
    State state = State.AVAILABLE;
    state.name(); // 返回 AVAILABLE
  • 另外,每一个枚举类型都有一个静态的 values() 方法:
    values() :它将返回一个包含全部枚举值的数组。

    1
    2
    3
    for (State state : State.values()) {
    // some code
    }

使用 enum 还有一个好处:它可以直接与 switch 语句结合着使用。(当然,JDK 1.7 以后 String 也可以这样使用了)

1
2
3
4
5
6
7
8
9
State state = State.AVAILABLE;
switch (state) {
case AVAILABLE:
case DISABLED:
case LOCKED:
default:
System.out.println(state.name());
break;
}

使用枚举替代常量

在枚举之前,在接口或者类中定义常量是一种很常见的用法:

1
2
3
4
5
public interface State {
int AVAILABLE = 0; // or String AVAILABLE = "正常";
int DISABLED = 1;
int LOCKED = 2;
}

现在这种用法经常被人诟病,其主要原因是:无法保证类型安全

而枚举既没有可以访问的构造器,又不能扩展。
虽然提供了 valueOf() 方法,但是其实例仍然是可控的。
枚举提供编译期的类型安全检查,也就是说:如果你在一个方法中声明了一个枚举类型的参数,那么就可以保证,传给这方法参数的非 null 对象引用肯定是合法的。