JavaRush /Java 博客 /Random-ZH /Java 中的枚举(java enum)
articles
第 15 级

Java 中的枚举(java enum)

已在 Random-ZH 群组中发布
在编程时,我们经常遇到需要限制某种数据类型的有效值集合。因此,例如,星期几可以有 7 个不同的值,一年中的月份可以有 12 个,季节可以有 4 个。为了解决此类问题,许多静态类型编程语言提供了一种特殊的数据类型 -枚举( enum)。枚举并没有立即出现在 Java 中。enum从 1.5 版本开始引入了专门的语言结构。到目前为止,程序员已经使用其他方法来实现枚举。 Java 中的枚举 (java enum) - 1

枚举构造

让我们从一个例子开始。让我们enum使用以下方法来描述存储季节的数据类型:
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
好吧,一个简单的使用示例:
Season season = Season.SPRING;
if (season == Season.SPRING) season = Season.SUMMER;
System.out.println(season);
结果SUMMER将被打印到控制台。我认为这个例子很明显,不需要解释。

枚举是一个类

通过声明enum,我们隐式地创建了一个派生自 的类java.lang.Enum。按照惯例,该构造enum Season { ... }相当于class Season extends java.lang.Enum { ... }。尽管编译器不允许我们显式继承,但仍然可以使用以下java.lang.Enum方法轻松验证它是否是继承的: enumreflection
System.out.println(Season.class.getSuperclass());
控制台上会显示以下内容:
class java.lang.Enum
实际的继承是由Java编译器自动为我们执行的。接下来,我们同意将编译器创建的用于实现枚举的类称为-class enum,并将枚举类型的可能值称为enum-a元素。

枚举成员是enum可静态访问的类的实例

元素是-class 的enum Season (WINTER, SPRING и т.д.)静态可访问实例。它们的静态可用性允许我们使用引用比较运算符执行比较。例子: enumSeason==
Season season = Season.SUMMER;
if (season == Season.AUTUMN) season = Season.WINTER;

枚举元素的名称和序列号

如前所述,任何enum类都会继承java.lang.Enum,其中包含许多对所有枚举有用的方法。例子:
Season season = Season.WINTER;
System.out.println("season.name()=" + season.name() + " season.toString()=" + season.toString() + " season.ordinal()=" + season.ordinal());
输出将是:
season.name()=WINTER season.toString()=WINTER season.ordinal()=0
方法name()toString()如下所示ordinal()。这些方法的语义是显而易见的。需要注意的是,这些方法enum都是从类继承的java.lang.Enum通过名称的字符串表示形式获取元素enum通常,任务是enum通过其字符串表示形式获取元素。为了这些目的,在每个enum类中,编译器自动创建一个特殊的静态方法:public static EnumClass valueOf(String name),它返回一个EnumClass名称等于 的枚举元素name。使用示例:
String name = "WINTER";
Season season = Season.valueOf(name);
执行代码的结果是,season 变量将等于Season.WINTER。请注意,如果未找到该元素,将抛出IllegalArgumentException,如果相等namenull将抛出NullPointerException。顺便说一下,这一点经常被遗忘。出于某种原因,许多人坚信,如果一个函数接受一个参数并在某些条件下抛出IllegalArgumentException,那么当将它传递给那里时,null肯定也会抛出IllegalArgumentException。但这不是重点。我们继续吧。 获取枚举的所有元素enum有时您需要在运行时获取类的 所有元素的列表。为了这些目的,enum编译器在每个类中创建一个方法public static EnumClass[] values()。使用示例:
System.out.println(Arrays.toString(Season.values()));
我们得到以下输出:
[WINTER, SPRING, SUMMER, AUTUMN]
请注意,类中既没有定义方法valueOf()也没有定义方法。相反,它们是在编译 -class 时由编译器自动添加的。 将您自己的方法添加到-class 您有机会将您自己的方法添加到-class 及其元素: 相同,但具有多态性: 最后一个示例演示了继承在. 稍后会详细介绍这一点。 Java中的继承允许您实现类层次结构,其对象在单个实例中创建并且可以静态访问。在这种情况下,元素可以包含自己的构造函数。让我们举个例子: 这里我们声明一个包含三个元素,和 的枚举。编译器将创建以下类和对象: values()java.lang.EnumenumenumenumJava 中的枚举 (java enum) - 2Java 中的枚举 (java enum) - 3enumenumenumenumJava 中的枚举 (java enum) - 4TypeINTINTEGERSTRING
  • Type- 类派生自java.lang.Enum
  • INT— 第一类的对象派生自Type
  • INTEGER— 第二类对象派生自Type
  • STRING— 第三类对象派生自Type
Object parse(String)将使用多态方法和构造函数创建三个派生类Type(..., boolean)。同时,类INTINTEGER和的对象STRING存在于单个副本中并且可以静态访问。您可以验证这一点:
System.out.println(Type.class);
System.out.println(Type.INT.getClass() + " " + Type.INT.getClass().getSuperclass());
System.out.println(Type.INTEGER.getClass() + " " + Type.INTEGER.getClass().getSuperclass());
System.out.println(Type.STRING.getClass()  + " " + Type.STRING.getClass().getSuperclass());
我们得到输出:
class Type
class Type$1 class Type
class Type$2 class Type
class Type$3 class Type
可以看到编译器创建了一个类Type和3个nested派生自Type.

具有继承的反编译枚举类

Type为了证实上述内容,我们还展示了对上面示例中的 枚举进行反编译的结果:Java 中的枚举 (java enum) - 5

枚举和参数多态性

读者可能会奇怪:“为什么上面的Type枚举不使用泛型呢? ” 事实上,Java 中enum禁止使用泛型。所以下面的例子将无法编译:
enum Type<T> {}

进一步研究

为了更深入地了解 Java 中枚举的工作原理,我建议您熟悉该类的源代码java.lang.Enum,并使用 Jad 反编译器来研究生成的代码。而且,研究Java库源代码对于理解Java中有多少机制是绝对必要的,并且对于面向对象设计来说是有用的参考。原始来源链接: http: //alexander.lds.lg.ua/
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION