Skip to content

枚举

在 java 中,我们可以通过 static final 来定义常量。例如,定义一周的七天:

java
class Weekday {
  public static final int SUN = 0;
  public static final int MON = 1;
  public static final int TUE = 2;
  public static final int WED = 3;
  public static final int THU = 4;
  public static final int FRI = 5;
  public static final int SAT = 6;
}

之后可以这样使用常量:

java
int day = 1;
if (day == Weekday.MON || day == Weekday.FRI) {
  System.out.println("working...");
}

但是,这样定义了之后,有一个严重的问题就是编译阶段无法检查每个值的合理性,例如:

java
//可以正常编译,但我们想要 today 只能是 0 - 6
int today = 9999;
if (today == Weekday.MON || today == Weekday.FRI) {
  System.out.println("working...");
}

enum

为了能让编译器自动检查某个值是否在枚举定义范围内,这时就可以使用 enum 来定义枚举类。

java
enum Weekday {
  SUN, MON, TUE, WED, THU, FRI, SAT;
}

public static void main(String[] args) {
  Weekday day = Weekday.MON;
  if (day == Weekday.MON || day == Weekday.FRI) {
    System.out.println("working...");
  }
}

int 定义的常量相比,使用 enum 定义枚举有以下好处:

  • enum 枚举本身带有类型信息,即 Weekday.MON 的类型是 Weekday,编译器会自动检查类型错误;
  • 不可能引用到枚举中未定义的值,因为编译无法通过;

枚举比较

使用 enum 定义的枚举类是一种引用类型。

正常情况下,引用类型比较,需要使用 equals() 方法,因为使用 == 比较,他比较的是两个引用类型的地址值是否相同。

但是,enum 定义的枚举类型例外。

因为 enum 定义的枚举类型,每个常量在 JVM 中只有一个唯一实例,所以可以直接使用 == 比较:

java
Weekday day = Weekday.MON;
if (day == Weekday.MON || day == Weekday.FRI) {
  System.out.println("working...");
}

if (day.equals(Weekday.MON)) {
  System.out.println("working...");
}

常用方法

方法描述
name()返回常量名称(方法不可被重写)
toString()返回常量名称(方法可被重写)
ordinal()返回枚举常量的顺序,从 0 开始计数
java
String s = Weekday.MON.name();
System.out.println(s); // "MON"

String s1 = Weekday.MON.toString();
System.out.println(s1); // "MON"

int n = Weekday.MON.ordinal();
System.out.println(n); // 1

高级用法

enum 定义的枚举,其内部默认使用一个构造器的,我们也可以手动添加构造器,实现为枚举值添加顺序值和中文名称的效果

java
enum Weekday {
  SUN(0, "星期天"),
  MON(1, "星期一"),
  TUE(2, "星期二"),
  WED(3, "星期三"),
  THU(4, "星期四"),
  FRI(5, "星期五"),
  SAT(6, "星期六");

  public final int dayValue;
  private final String name;

  Weekday(int dayValue, String name) {
    this.dayValue = dayValue;
    this.name = name;
  }

  @Override
  public String toString() {
    return this.name;
  }
}
java
public static void main(String[] args) {
  Weekday day = Weekday.MON;

  System.out.println(day.dayValue); 	// 1
  System.out.println(day.toString()); // "星期一"
  System.out.println(day.name()); 	// "MON"
}

注意

如果想获取枚举常量的名字,首选 name() 方法,而不是 toString()

Released under the MIT License.