首页 > 编程笔记

Java枚举用法详解

在 Java 中,枚举(Enum)是一种有确定取值区间的数据类型,它本质上是一种类,具有简洁、安全、方便等特点。可以这样理解,枚举的值被约束到一个特定的范围,只能取这个范围以内的值。

在了解枚举的具体概念之前,我们先来思考一个问题:为什么要有枚举呢?

我们在描述对象的一些属性特征时,可选择的值是有一个特定范围的,即该属性的值不能随便定义。比如:
出于对数据的安全性考虑,类似这种有特定取值范围的数据我们就可以使用枚举来描述,这就是使用枚举的意义所在。

枚举指由一组常量组成的类型,指定了一个取值区间,我们只能从这个区间中取值。再来看枚举的定义,在没有枚举之前,我们需要定义一个类来描述周一到周日,可以通过定义静态常量的方式来完成,例如:
public class Week {
   public static final int MONDAY = 0;
   public static final int TUESDAY = 1;
   public static final int WEDNESDAY = 2;
   public static final int THURSDAY = 3;
   public static final int FRIDAY = 4;
   public static final int SATURDAY = 5;
   public static final int SUNDAY = 6;
}

这种方式是可以完成需求的,但是编写起来会比较麻烦,用 int 类型的数据来描述周几也不是很直观,如果使用枚举类型就会方便很多,例如:
public enum Week {
   MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY;
}
枚举的定义与类很相似,使用 enum 关键字来描述,基本语法如下:
public enum 枚举名{
    值1,值2,值3...
}
注意,枚举中的常量使用逗号进行分割,看到这里有的读者可能会有疑惑,枚举中的常量值是什么呢?枚举中的每一个常量都对应的是一个枚举实例,只不过表示的含义不同。

拿上面这个例子来说,Java 在编译期会帮我们生成一个 Week 类,并且继承自 java.lang.Enum,被 final 修饰,表示该类不可被继承。同时还生成了 7 个 Week 的实例对象分别对应枚举中定义的 7 个日期,因为枚举的静态常量直接对应其实例化对象,所以对于枚举的使用如下面的代码所示:
public class Test {
   public static void main(String[] args) {
      Week week = Week.MONDAY;
      System.out.println(week);
   }
}
运行结果为:

MONDAY


编译期生成的类如下:
final class Week extends Enum {
    public static final Week MONDAY;
    public static final Week TUESDAY;
    public static final Week WEDNESDAY;
    public static final Week THURSDAY;
    public static final Week FRIDAY;
    public static final Week SATURDAY;
    public static final Week SUNDAY;
    private static final Week $VALUES[];
    static {
       MONDAY = new Week("MONDAY", 0);
       TUESDAY = new Week("TUESDAY", 1);
       WEDNESDAY = new Week("WEDNESDAY", 2);
       THURSDAY = new Week("THURSDAY", 3);
       FRIDAY = new Week("FRIDAY", 4);
       SATURDAY = new Week("SATURDAY", 5);
       SUNDAY = new Week("SUNDAY", 6);
       $VALUES = (new Week[] { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY });
    }
    public static Week[] values() {
       return (Week[])$VALUES.clone();
    }
    public static Week valueOf(String s) {
       return (Week)Enum.valueOf(com/southwind/Week, s);
    }
    private Week(String s, int i) {
       super(s, i);
    }
}
解读一下这个类,首先定义了 7 个 Week 类型的静态常量和一个 Week 类型的静态数组常量。同时定义了一个私有的构造函数,String 类型的参数即当前枚举对象的值,int 类型的参数为它的下标。

静态代码块中通过私有构造函数对 7 个静态常量以及静态数组常量赋值,所以上面程序中打印的枚举值其实就是创建该对象时传入的 String 类型参数,如"MONDAY"。

同时该类还为我们提供了两个静态方法 values() 和 valueOf(String s),values() 方法可以返回该枚举的所有常量,vauleOf(String s) 可以通过字符串s创建对应的枚举对象,具体操作如下:
public class Test {
   public static void main(String[] args) {
      Week[] weeks = Week.values();
      for(Week week:weeks) {
         System.out.println(week);
      }
      System.out.println("----------");
      Week week = Week.valueOf("MONDAY");
      System.out.println(week);
   }
}
运行结果为:

MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
----------
MONDAY

推荐阅读