iAfoot-Java 枚举

152 阅读6分钟

枚举

JDK 5之前的Java版本缺失的一项特性是枚举形式最简单的枚举(enumeration)是一系列具有名称的常量。从JDK5开始,枚举被添加到了Java语音中。

在Java中、枚举定义了一种类类型。通过将枚举定义为类,极大地扩展了枚举的功能。例如在Java中,枚举可以具有构造函数、方法以及实例变量

枚举的基础知识

创建枚举需要使用关键字enum。例如,下面是一个简单的枚举,其中列出了各种苹果的品种:

标识符Jonathan、GoldenDel等被称为枚举常量每个枚举常量被隐式声明为Apple的公有、静态final成员。此外,枚举常量的类型是声明它们的枚举的类型,对于这个例子为Apple。在Java语言中,这些常量被称为是“自类型化的”(self-typed)。

尽管枚举定义了类类型,却不能使用new实例化枚举。反而,枚举变量的声明和使用方式在许多方面与基本类型相同。例如,下面运行这行代码将ap声明为Apple枚举类型的变量:

因为ap是Apple类型,所以只能被赋值为(或包含)在Apple枚举中定义的那些值。例如,下面这行代码将ap赋值为RedDel:

注意在符号RedDel之前的Apple。

可以使用关系运算符“==”比较两个枚举变量的相等性。例如,下面这条语句比较ap的值和GoldenDel常量:

枚举值也可以用于控制switch语句。当然,所有case语句使用的常量的枚举类型,都必须与switch表达式使用的枚举类型相同。例如,下面这条switch语句是完全合法的:

注意在case语句中,枚举常量的名称没有使用枚举类型的名称进行限定。因为switch表达式中的枚举类型已经隐式指定了case常量的枚举类型,所以在case语句中不需要使用枚举类型的名称对常量进行限定。实际上,如果试图这么做的话,会造成编译时错误。

当显示枚举常量时,例如在pringln()语句中,会输出枚举常量的名称。例如下面这条语句:

下面的程序用到了刚才介绍的所有内容,并演示了Apple枚举:

values()和valueOf()方法

所有枚举都自动包含两个预定义方法:values()和valuesOf()。它们的一般形式如下所示:

values()方法返回一个包含枚举常量列表的数组,valueOf()方法返回与传递到参数str的字符串相对应的枚举常量。例如,对于前面显示的Apple枚举,Apple.valueOf(“Winesap”)的返回类型是Winesap。

下面的程序演示了values()和valueOf方法:

为了进行说明,创建变量allapples,并将其赋值为对枚举数组的引用。但是,这个步骤不是必需的,因为可以像下面这一编写for循环,从而消除对allapples变量的需要:

现在,请注意通过调用valueOf()方法获取与名称Winesap对应的枚举值的方式:

正如前面所解释的,valueOf()方法返回与以字符串形式表示的常量名称相关联的枚举值。

Java 枚举是类类型

Java枚举是类类型。虽然不能使用new实例化枚举,但是枚举却有许多和其他类相同的功能。可以为枚举提供构造函数、添加实例变量和方法,甚至可以实现接口。

需要理解的重要一点是:每个枚举常量都是所属枚举类型的对象。因此,如果为枚举定义了构造函数,那么当创建每个枚举常量时都会调用该构造函数此外,对于枚举定义的实例变量,每个枚举常量都有它自己的副本。例如,分析下面版本的Apple枚举:

这个版本的Apple枚举添加了3个内容:第1个内容是实例变量price,用于保持每种苹果的价格;第2个内容是Apple构造函数,它以苹果的价格作为参数;第3个内容是getPrice()方法,用于返回price变量的值。 当在main()方法中声明变量ap时,对于每个特定的常量调用Apple构造函数一次。注意指定构造函数参数的方法,通过将他们放置在每个常量后面的圆括号中来加以指定,如下所示:

这些数值被传递给Apple()的参数p,然后将这些值付给price变量。再强调一次,为每个常量调用构造函数一次。 因为每个枚举常量都有自己的price变量副本,所以可以调用getPrice()方法来获取指定类型苹果的价格。例如在main()方法中,通过下面的调用获取Winesap的价格:

尽管前面的例子只包含一个构造函数,但是枚举可以提供两种甚至更多种重载形式,就像其他类那样。例如,下面版本的Apple提供了一个默认构造函数,可以将price变量初始化为-1,表明不能获得价格数据:

注意在这个版本中,没有为RedDel提供参数。这意味着会调用默认构造函数,并将RedDel的price变量设置为-1。 枚举有两条限制:第一,枚举不能继承其他类;第二,枚举不能是超类。这意味着枚举不能扩展。在其他方面,枚举和其他类很相似。需要记住的关键是:每个枚举常量都是定义它的类的对象

枚举继承自枚举类

所有枚举都自动继承超类java.lang.Enum,这个类定义了所有枚举都可以使用的一些方法。

获取用于指示枚举常量在常量列表中位置的值,这称为枚举常量的序数值。通过ordinal()方法可以检索序数值,该方法的声明如下所示:

该方法返回调用常量的序数值,序数值从0开始

使用compareTo()方法比较相同类型的两个枚举常量的序数值,该方法的一般形式如下:

enum-type是枚举的类型,e是和调用常量进行比较的常量调用常量和e必须是相同的枚举。如果调用常量的序数值小于e的序数值,那么compareTo()方法返回负值;如果两个序数值相同,就返回0;如果调用常量的序数值大于e的序数值,就返回正值

使用equals()方法来比较枚举常量和其他对象的相等性,该方法重写了Object类定义的equals()方法。 请记住,可以使用“==”比较两个枚举引用的相等性。

下面的程序演示了ordinal()、compareTo()以及equals()方法: