Java 1.5发行版中增加了两个新的引用类型家族:一种新的类称作枚举类型(enum type),一种新的接口称作注解类型(annotation type)。
>枚举
枚举类型是指由一组固定的常量组成合法值的类型。
>创建和使用枚举
定义一个简单的enum
enum Apple{
FUJI,PIPPIN,CRANNY_SMITH
}
创建枚举用enum关键字,标识符FUJI、PIPPIN等被称为枚举常量,每个枚举常量被隐式声明为Apple的公有、静态、final成员。枚举常量的类型是声明它们的枚举的类型,如上例代码中是Apple。在Java语言中,这些常量被称为”自类型化的”(sefl-type),其中的”自”指封装常量的枚举。对以上代码编译后会看到编译器将enum类型单独编译成字节码文件Apple.class,使用javap查看
定义了枚举后,可以创建枚举类型的变量,然而,虽然枚举定义了类类型,却不用new实例化枚举,枚举变量的使用方式很大程度上与基本类型相同。获取Apple枚举类的一个实例:
Apple a = Apple.FUJI;
>构造器
枚举类是class,在枚举类型中有构造器、方法、数据域。枚举类的构造器是在构造枚举常量的时候被调用。 每个枚举常量都是所属枚举类型的对象。如果为枚举定义了构造函数,当创建每个枚举常量是都会调用该构造函数。对于枚举定义的实例变量,每个枚举常量都有它自己的副本。
代码示例
package com.afy.enumdemo;
enum Apple{
Jonathan(10), GoldenDel(9),RedDel(12),Winesap(15),Cortland(8);
private int price; //price of each apple
//Constructor
private Apple(int p) {
price = p;
}
int getPrice(){
return price;
}
}
class AppleEnumDemo {
public static void main(String[] args) {
Apple ap;
//Display price of Winesap.
System.out.println("Winesap costs" + Apple.Winesap.getPrice() + "cents.\n");
//Display all apples and prices.
System.out.println("All apple price:");
for(Apple a : Apple.values())
System.out.println(a + "cost" + a.getPrice() + "cents.");
}
}
这段代码中有实例变量price,有Apple构造函数,有getprice()方法。每个常量后面圆括号中的数值是指定构造函数参数,这些数值被传递给Apple()方法的参数p,然后将这些值赋给price变量.当在main()方法中声明变量ap时,对于每个特定的常量调用Apple的构造函数一次
每个枚举变量都由自己的price变量副本,可以调用getPrice()方法来获取指定类型苹果的价格,若获取Cortland的价格:
Apple.Cortland.getPrice()
也可以通过for循环获取所有品种的苹果价格。由于每个枚举常量都有price变量的副本,所以与枚举常量关联的值是独立的,并且和与其他常量关联的值不同。将枚举作为类实现像Java一样,才有这样强大的功能。
针对构造器,就像其他类一样,枚举提供多种重载形式。可以将price变量初始化为-1.表明不能获得价格数据:
//Use an enum constructor.
enum Apple{
Jonathan(10),GoldenDel(9),RedDel,Winesap(15),Cortland(8);
private int price; //price of each apple
//Constructor
Apple(int p){
price = p;
}
//Overloaded constructor
Apple(){
price = -1;
}
int getPrice(){
return price;
}
}
这里没有给RedDel赋参数,这样会调用默认构造函数,并将RedDel的price变量设置为-1。
构造器只能使用私有private访问控制符,而不应有public构造器,以保证外部代码无法新构造枚举类的实例,我们已知道枚举常量是public static final的常量,即枚举对象的属性不应允许改动。然而枚举类的方法和数据域允许外部访问。
枚举switch的语句用法
枚举值可以用于控制switch语句,可以在switch表达式中使用Enum定义的枚举类的对象作为表达式,case子句可以直接使用枚举值的名字,枚举常量的名称没有使用枚举类型的名称进行限定,如直接用Jonathan,而不用Apple.Jonathan,因为switch表达式中的枚举类型已经隐式指定了case常量的枚举类型,故不使用枚举类型的名称对常量进行限定,而如果这样试图这么做的话,会造成编译时错误。如
System.out.println(Apple.Jonathan);
这样做打出“Jonathan”。
示例代码
package com.afy.enumdemo;
enum Apple1 {
Jonathan,GoldenDel,RedDel,Winesap,Cortland
}
class EnumSwitchDemo {
public static void main(String[] args) {
Apple1 ap ;
ap = Apple1.RedDel;
//OUtput an enum value.
System.out.println("value of ap is: " + ap);
System.out.println();
ap = Apple1.GoldenDel;
//compare two enum values
if (ap==Apple1.GoldenDel) {
System.out.println("ap contains GoldenDel.\n");
}
//Use an enum to control a switch statement,
switch (ap) {
case Jonathan:
System.out.println("Jonathan is red");
break;
case GoldenDel:
System.out.println("Golden delicios is yellow");
break;
case RedDel:
System.out.println("Red Delicious is red");
break;
case Winesap:
System.out.println("Winesap is red");
break;
case Cortland:
System.out.println("Cortland is red");
break;
}
}
}
values()和valueOf()方法
所有枚举都自动包含两个预定义方法:values()和valueOf()。它们的一般形式如下:
public static enum-type [] values()
public static enum-type [] valueOf(String str)
values()方法返回一个包含枚举常量列表的数组,valueOf()方法返回与传递到参数str的字符串相对应的枚举常量。enum-type是枚举类型,如Apple枚举,Apple.vallueOf(“Winesap”)返回的是Winesap。
代码示例
package com.afy.enumdemo;
enum Apple2{
Jonathan,GoldenDel,RedDel,Winesap,Cortland
}
public class ValuesAndValueOfDeme {
public static void main(String[] args) {
Apple ap;
System.out.println("Here are all Apple constants:");
//use values()
Apple allapples[] = Apple.values();
for (Apple a : allapples) {
System.out.println(a);
}
System.out.println();
//use valueOf()
ap = Apple.valueOf("Winesap");
System.out.println("ap contains " + ap);
}
}
这里使用for-each风格的for循环来遍历values()方法返回的常量数组。为了进行说明,创建变量allapples,并将其赋值为对枚举数组的引用,但不一定要这样,可以如下:
for(Apple a : Apple.values())
System.out.println(a);
枚举的限制
1. 枚举不能继承其他类;
2. 枚举不能是超类,这意味着枚举不能扩展;
除此之外,枚举与其他类相似,尤其要注意的是:每个枚举常量都是定义它的类的对象。
>枚举都继承Enum类
尽管声明枚举时不能继承超类,但是
java.lang.Enum这个类定义了所有枚举都可以使用的一些方法。
>枚举实现接口
枚举和Java其他类一样,可以实现一个或多个接口。