概述:
最简单的枚举形式就是用来定义新数据类型的命名常量列表, 枚举类型 的对象只能包含该列表定义的值。因此,枚举为精准定义包含固定条目有效值的新数据类型提供了一种方式。
枚举在日常生活中很常见。例如,月份的枚举包含1月到12月这12个数据,一周各天的枚举是星期一、星期二、星期三、星期四、星期五、星期六和星期天。
从编程的角度来看,枚举在需要定义一组代表条目集合的值时很有用。例如,可使用枚举来代表一组状态代码,例如:成功、失败、等待和重试等来表示某种动作的进度。在过去,我们把这种值定义为final的,但是用枚举就显得更加结构化,我们通过示例代码( 列出各种交通工具 )来体会一下这两种实现方式的差别:
用final修饰的方式:
/** * Created by 摆技 */public class Transport { public static final int CAR =1; public static final int TRUCK=2; public static final int AIRPLANE=3; public static final int TRAIN=4; public static final int BOAT=5; }
枚举方式:
/**
* Created by 摆技
*/public enum TransportEnum {
CAR, TRUCK, AIRPLANE, TRAIN, BOAT
}
枚举的基础知识
枚举用enum关键字创建,在上例中,标识符CAR、TRUCK等称为枚举常量,它们都被隐式的声明为一个public final static的TransportEnum的成员。在java中,这些常量被称为自我类型化(self-typed)。
定义了枚举之后,我们可以创建枚举的常量。但是尽管枚举定义了一个类类型,却不能使用new来 实例化 。应该像处理基本数据类型那样来声明和使用枚举变量。例如:
TransportEnum tp;
由于tp是TransportEnum类型的,因此只能向他赋值枚举定义的值:
tp = TransportEnum.TRAIN;
可以使用关系运算符==来判断两个枚举常量是否相等。例如:
if(tp == TransportEnum.TRAIN) // ...
还可以使用枚举值来控制 switch 语句,当然,所有的case语句都必须使用来自switch表达式所用枚举中的 Enum 常量。例如:
/**
* Created by 摆技
*/public class Test {
public static void main(String[] args) {
TransportEnum tp = TransportEnum.TRAIN;
switch(tp) {
case CAR:
// TODO
break ;
case TRUCK:
// TODO
break;
case AIRPLANE:
// TODO
break;
case TRAIN:
// TODO
break;
case BOAT:
// TODO
break;
default:
// TODO
}
}
}
注意,在case语句中,枚举常量的名称没有使用枚举类型名称来限制,也就是说,使用TRAIN而不是TransportEnum.TRAIN。这是因为switch表达式中的枚举类型已经隐式的制定了case常量的枚举类型,也就没有必要使用枚举类型名称来限定了。
JAVA中的枚举本质上是类类型
前面的实例中,虽然说明了如何创建和使用枚举,但是并没有揭示的全部功能。与其他语言实现枚举的方式不同,JAVA将枚举实现没类类型。尽管不会使用new实例化枚举,但是枚举的表现非常像其他类类型, 本质上使用enum关键字创建的枚举类型并编译后事实上也是一个类类型而且该类是fianl的并且还继承了java.lang.Enum 。这使得JAVA的枚举有了其他更为强大的功能,例如,可以给枚举提供 构造方法 ,添加实例变量和实例方法。甚至实现接口。
下面我们需要了解一下values()和valueOf()方法,所有枚举都拥有这两个预定的方法。它们的基本形式如下图所示:
public static enum-type[] values(); public static enum-type valueOf(String str);
Values()方法返回一个包含枚举常量列表的数组。valueOf()方法返回一个枚举常量,其值对应传进来的str字符串。这两个方法中enum-type是相同的。例如前面的TransportEnum枚举中,TransportEnum.valueOf(“TRAIN”)的返回值类型是TransportEnum,返回值是TRAIN。下面的程序演示了values()和valueOf()方法:
/**
* Created by 摆技
*/public class Test {
public static void main(String[] args) {
System.out.println("列出所有交通工具:");
//使用values()方法
TransportEnum[] tps = TransportEnum.values();
for(TransportEnum tp : tps) {
System.out.println(tp);
}
System.out.println("-----------------------------");
//使用valueOf()
TransportEnum tp = TransportEnum.valueOf("TRAIN");
System.out.println(tp);
}
}
枚举类型的构造方法、成员方法、成员变量
每一个枚举常量都是一个枚举类型的对象,理解这一点很重要。因此,枚举可以定义构造方法、成员方法和成员变量。以下三点需要掌握:
1)当定义枚举的构造方法的时候,会在创建每个枚举常量的时候调用。
2)每个枚举常量都可以调用枚举定义的任何成员方法。
3)每个枚举常量都包含实例变量的副本。
我们通过改造TransportEnum(为每种交通工具提供一种常见的速度)来验证以上三点:
/**
* Created by 摆技
*/public enum TransportEnum {
CAR(65), TRUCK(55), AIRPLANE(600), TRAIN(70), BOAT(22);
// 为交通工具提供 speed 属性
private int speed;
TransportEnum(int speed) {
this.speed = speed;
}
int getSpeed() {
return this.speed;
}
}
我们给TransportEnum添加了四项内容:
1)实例变量speed,用来保存每种交通工具的速度。
2)TransportEnum(int)构造方法
3)getSpeed()方法,返回speed的值
4)通过在常量后面添加()的方式指定构造方法的实参
总结:
你可记得,前面我们说过枚举本质上是类类型。每一个枚举被编译之后,都会变成一个final的类( 所以枚举有一个限制是不能被继承 ),并且该类继承了java.lang.Enum( 所以枚举还有一个限制是不能继承另一个类 ),这是枚举的本质。请务必牢记!!!
既然枚举是继承了java.lang.Enum的类,那么大家看完文章后有没有必要回去找找API,看看java.lang.Enum类都有什么方法?
此处,我给大家一个问题,大家可以在评论区讨论:
我们说枚举可以替换final变量的方式,那么JAVA枚举的出现,使得final变量过时了吗?