enum1.产生背景

今天我们将探讨 Java 中的另一种数据类型:enum. 这个名字enum来自单词enumeration。这个数据类型是什么,它有什么用?

有时程序员需要创建一个新的数据类型,其可能的值被限制在一个小的固定列表中。

比如一个DayOfTheWeek类型只能取值MONDAY, TUESDAY, WEDNESDAY, ... 一共有7个值。或者一个Month类型只能取值JANUARY, FEBRUARY, MARCH, ... 总共有 12 个值。

当然,您可以使用数字(类型int):1— 星期一, — 星期二,等等。但是有人可能会不小心将无效值分配给您的变量2,例如8or 。0

您可能很容易遇到这样一种情况:一个程序员认为星期几(或一年中的几个月)是从零开始编号的,而其他人则希望他们的编号从一开始,等等。

这就是 Java 引入一种由有限值集enum组成的数据类型的原因。


2.声明类型

声明一个新的enum数据类型看起来像这样:

enum TypeName
{
   VALUE1,
   VALUE2,
   VALUE3
}

哪里TypeName是新类型(类)的名称,可能的值用逗号分隔并用花括号括起来:Value1, Value2, Value3.

例如,让我们创建自己的DayOfTheWeek enum

代码 笔记
enum Day
{
   MONDAY,
   TUESDAY,
   WEDNESDAY,
   THURSDAY,
   FRIDAY,
   SATURDAY,
   SUNDAY
}
Day类型

周一
周二
周三
周四
周五
周六
周日

以下是如何为我们的新类型的变量赋值:

Day day = Day.MONDAY;

例子:

代码 笔记
Day day = Day.FRIDAY;
System.out.println(day);
屏幕输出将是:
FRIDAY


3.方法enum

一个enum类型有几个内置方法,其中两个非常有趣:

静态values()方法返回该类型所有值的数组enum

代码 笔记
Day[] days = Day.values();

for (Day day: days)
   System.out.println(day);







System.out.println(days[2]);
变量days存储一个包含类型值的数组Day(7 个元素)

在屏幕上显示数组的内容:
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY

WEDNESDAY

ordinal()方法返回常量的序数。enum你在一个值而不是一个类上调用它enum

代码 控制台输出
System.out.println(Day.MONDAY.ordinal());
System.out.println(Day.FRIDAY.ordinal());
System.out.println(Day.SUNDAY.ordinal());
0
4
6


4.转换为类

实际上,这里并没有什么神奇之处。编译器只是给了我们一些语法糖。在编译时,Day枚举被转换为普通类:

代码,简化版 笔记
public class Day
{
   public static final Day MONDAY = new Day(0);
   public static final Day TUESDAY = new Day(1);
   public static final Day WEDNESDAY = new Day(2);
   public static final Day THURSDAY = new Day(3);
   public static final Day FRIDAY = new Day(4);
   public static final Day SATURDAY = new Day(5);
   public static final Day SUNDAY = new Day(6);

    private static final Day[] array = {MONDAY, TUESDAY,
      WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY};

   private final int value;

   private Day (int value)
   {
      this.value = value;
   }

   public int ordinal()
   {
      return this.value;
   }

   public static Day[] values()
   {
      return array;
   }
}
Dayclass

静态常量列表包含







枚举所有值的Day数组存储特定对象


值的变量 该类是私有的,这意味着该类的对象只能在该类内部创建。必须在对象上调用 该方法。 它返回对象的值——字段。该方法返回一个包含类 的所有值的静态数组Day

DayconstructorDayDay



ordinalDay

value


Day

如果我们从类中删除所有静态方法和变量Day,我们将得到以下内容:

代码 笔记
public class Day
{
  private int value;

  private Day (int value)
  {
    this.value = value;
  }

  public int ordinal()
  {
    return this.value;
  }
}


变量存储对象value的值对象只能在类内部创建,因为构造函数是. 该方法返回对象的。 Day

DayDayprivate




ordinal()valueDay

换句话说,这里没有发生任何可怕的事情。编译器创建Day类,添加表示值的常量enum,添加必要的方法,并生成类构造函数private。稍后我们将看看构造函数是如何工作的。

希望现在清楚为什么我们以这种方式为变量赋值:

Day day = Day.MONDAY;

MONDAY只是Day类中的静态字段(常量)。从类外部访问静态方法和字段时,必须在字段或方法的名称之前指明类名。



5.更多方法enum

每个enum班级都有几个有趣的特点。

与字符串相互转换

要将枚举对象转换为字符串,您需要调用它的toString()方法。

String str = Day.MONDAY.toString();

要从另一个方向转换(从字符串到对象Day),您可以使用静态valueOf()方法:

Day day = Day.valueOf("MONDAY");

它非常方便,在很多情况下都会很有帮助。

转换为数字并再次返回

您已经知道如何将enum对象转换为数字:调用ordinal()方法:

int index = Day.MONDAY.ordinal();

要在另一个方向(从数字到对象Day)转换,您需要一个更透明的结构:

Day day = Day.values()[2];

例子:

代码 笔记
Day day = Day.MONDAY;
int index = day.ordinal();
Day newDay = Day.values()[index+2];
星期一
获取星期一的索引: 0
星期一后第 2 天的星期几

要点:因为enum值是一组固定的常量,所以可以使用 == 比较它们。换句话说,您不能拥有两个MONDAY具有不同地址的相同对象。每个枚举值只存在一个实例。这意味着使用 == 比较枚举变量将始终有效。



6. 将自己的方法添加到enum

因为anenum在编译时变成了一个普通的类,你可以在里面声明方法。这些方法只是简单地添加到编译器生成的类中。例如,假设我们希望我们Day enum返回一个枚举值列表而不是一个数组。

然后我们可以添加以下代码:

代码 笔记
enum Day
{
   MONDAY,
   TUESDAY,
   WEDNESDAY,
   THURSDAY,
   FRIDAY,
   SATURDAY,
   SUNDAY;

   public static List<Day> asList()
   {
      ArrayList<Day> list = new ArrayList<Day>();

      Collections.addAll(list, values());

      return list;
   }

}








值列表后需要分号。



创建ArrayList对象

添加方法返回的数组中的值values()
返回列表。

现在可以在代码中调用此方法:

代码 笔记
List<Day> list = Day.asList();
list变量将存储 的所有值的列表Day enum