枚举
从 JDK 5 开始, 枚举被添加到了 Java 语言中, 和其它语言中的描述相似, 但是这种相似只是表面上的.
枚举的基础知识
创建枚举需要使用 enum
关键字, 例如:
enum Apple {
Jonathan, GoldenDel, RedDel, Winesap, Cortland
}
标识符 Jonathan
, GoldenDel
等被称为枚举常量. 每个枚举常量被隐式声明为 Apple 的公有,静态 final 成员.
此外, 枚举常量的类型是声明它们的枚举类型, 对于这个例子为 Apple.
定义了枚举之后, 可以创建枚举类型的变量. 但是, 尽管枚举定义了类类型, 却不能使用 new
实例化枚举. 反而, 枚举变量的声明和使用方式在许多方面与基本类型相同.
下面这行代码将 ap 声明为 Apple 枚举类型的变量:
Apple ap;
因为 ap
是 Apple 类型, 所以只能被赋值为(或包含)在 Apple 枚举中定义的那些值.
例如, 下面这行代码将 ap
赋值为 RedDel;
ap = Apple.RedDel;
可以使用关系运算符 ==
比较两个枚举常量的相等性. 例如, 下面这条语句比较 ap
的值和 GoldenDel
常量:
if (ap == Apple. GoldenDel) // ...
枚举值也可以用于控制 switch
语句. 当然, 所有的 case
语句使用的常量的枚举类型, 都必须与 switch
表达式使用的枚举类型相同.
switch (ap) {
case Jonathan:
// ...
case Winesap:
// ...
注意在
case
语句中, 枚举常量的名称没有使用枚举类型的名称进行限定. 也就是说, 使用的是Winesap
而不是Apple.Winesap
.
这是因为 switch 表达式中的枚举类型已经隐式指定了 case 常量的枚举类型, 所以在 case 语句中不需要使用枚举类型的名称对常量进行限定. 实际上, 如果试图这么做的话, 会造成编译时错误.
values() 和 valuesOf() 方法
所有枚举都自动包含两个预定义方法: values() 和 valuesOf() 方法. 它们的一般形式如下所示:
public static enum-type [ ] values()
public static enum-type valueOf(String str)
values() 方法返回一个包含枚举常量列表的数据, valueOf()方法返回与传递到参数 str 的字符串相对应的常量.
Java 枚举是类类型
Java 枚举是类类型. 虽然不能使用 new
实例化枚举, 但是枚举却又许多和类相同的功能.
枚举定义了类, 这为 Java 枚举提供了超乎寻常的功能. 例如, 可以为枚举提供构造函数, 添加实例变量和方法, 甚至可以实现接口.
需要理解的重要一点是: 每个枚举常量都是枚举类型的对象. 因此, 如果为枚举定义了构造函数, 那么当创建每个枚举常量时都会调用该构造函数.
分析下面 Apple 枚举:
enum Apple{
Jonathan(10), GoldenDel(9), RedDel(20), Winesap(15), Cortland(8);
private int price;
Apple(int p) { price = p;}
int getPrice() { return price; }
}
这个版本的 Apple 枚举添加了三个内容: 第一个内容是实例变量 price, 用于保存每种苹果的价格; 第二个内容是 Apple 构造函数, 它以苹果的价格作为参数; 第三个内容是 getPrice() 方法, 用于返回 Price 变量的值.
当在 main()
方法中声明变量 ap 时, 对于每个特定的常量调用 Apple 构造函数一次.
注意指定构造函数参数的方式, 通过将它们放置到每个常量后面的圆括号中来加以指定, 如下所示:
Jonathan(10), GoldenDel(9), RedDel(20), Winesap(15), Cortland(8);
这些数值被传递给 Apple()
的参数 p, 然后将这些值赋值给 price
变量. 再强调一次, 为每个常量调用构造函数一次.
因为每个枚举常量都有自己的 price
变量副本, 所以可以调用 getPrice()
方法来获取指定类型苹果的价格.
Apple.Winesap.getPrice();
枚举继承自 Enum 类
尽管声明枚举时不能继承超类, 但是所有枚举都自动继承超类 java.lang.Enum
, 这个类定义了所有枚举都可以使用的一些方法.
可以获取用于指示枚举常量在常量列表中位置的值, 这种称为枚举常量的序数值. 通过 ordinal() 方法可以检索序数值, 该方法的声明如下所示:
final int ordinal();
该方法返回调用常量的序数值, 序数值从0开始. 因此 Apple 枚举中, Jonathan 的序数值为 0, GoldenDel 的序数值为 1.
可以使用 compareTo()
方法比较相同类型的两个枚举常量的序数值, 该方法的一半形式如下:
final int compareTo( enum-type e );
其中, enum-tpye 是枚举的类型, e 是和调用常量进行比较的常量. 请记住, 调用常量和 e 必须是相同的枚举.
如果调用常量的序数值小于 e 的序数值, 那么 compareTo()
方法返回负值; 如果两个序数值相同, 返回0; 如果调用常量的序数值大于 e 序数值, 就返回正值.