枚举是一种数据类型,具有集合的一些特点,可以存放多个元素,但存储对象有限且固定,枚举也有比较常见的使用场景。如性别(男、女),颜色(红、黄、蓝),星期(星期一、星期二…星期日)均可以使用枚举存储。
从源码角度:
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
}
实质上Enum是java.lang.Enum 的子类。
//定义颜色枚举
public enum ColorEnum {
RED,YELLOW,BLUE
}
分别编译文件和反编译
> javac ColorEnum.java
> javap ColorEnum.class
Compiled from "ColorEnum.java"
public final class com.qxy.config.ColorEnum extends java.lang.Enum<com.qxy.config.ColorEnum> {
public static final com.qxy.config.ColorEnum RED;
public static final com.qxy.config.ColorEnum YELLOW;
public static final com.qxy.config.ColorEnum BLUE;
public static com.qxy.config.ColorEnum[] values();
public static com.qxy.config.ColorEnum valueOf(java.lang.String);
static {};
}
从反编译文件中可以得出以下结论:
枚举的特性,归结起来就是一句话:
除了不能继承,基本上可以将 enum 看做一个常规的类。
public enum ColorEnum {
RED,YELLOW,BLUE
}
//ordinal():返回实例声明时的次序,从 0 开始。
public static void main(String[] args) {
System.out.println(ColorEnum.RED.ordinal());//0
}
注意一个细节:如果要为 enum 定义方法,那么必须在 enum 的最后一个实例尾部添加一个分号[;]。
此外,在 enum 中,必须先定义实例,不能将字段或方法定义在实例前面。否则,编译器会报错。
示例:
public enum ColorEnum {
RED("red"),YELLOW("yellow"),BLUE("blue");
private String code;
// 有参构造方法
ColorEnum(String code) {
this.code = code;
}
//普通方法
public String getCode() {
return code;
}
//静态方法
public static void main(String[] args) {
System.out.println(ColorEnum.RED.ordinal());
}
}
enum 不可以继承另外一个类,当然,也不能继承另一个 enum ?因为 enum 实际上都继承自 java.lang.Enum 类,而 Java 不支持多重继承,所以 enum 不能再继承其他类,当然也不能继承另一个 enum。但是枚举可以定义接口并实现。
示例:
public interface IEnum<E extends Serializable> {
E getValue();
}
//实现Enum接口
public enum ColorEnum implements IEnum<String>{
RED("red"),YELLOW("yellow"),BLUE("blue");
private String code;
// 有参构造方法
ColorEnum(String code) {
this.code = code;
}
//静态方法
public static void main(String[] args) {
ColorEnum red = ColorEnum.RED;
System.out.println(red.ordinal() + ":" + red.getValue());//0:red
}
//重写接口方法,并返回值
@Override
public String getValue() {
return code;
}
}
public static void main(String[] args) {
//获取枚举元素
System.out.println(ColorEnum.RED);
System.out.println(ColorEnum.RED.toString());
System.out.println("-------------");
//获取枚举属性
System.out.println(ColorEnum.RED.code);
System.out.println(ColorEnum.RED.getValue());
}
//
RED
RED
-------------
red
red
使用 switch 语句来写状态机。JDK7 以后,switch 已经支持 int、char、String、enum 类型的参数。这几种类型的参数比较起来,使用枚举的 switch 代码更具有可读性。
public class StateMachineDemo {
public enum Signal {
GREEN, YELLOW, RED
}
public static String getTrafficInstruct(Signal signal) {
String instruct = "信号灯故障";
switch (signal) {
case RED:
instruct = "红灯停";
break;
case YELLOW:
instruct = "黄灯请注意";
break;
case GREEN:
instruct = "绿灯行";
break;
default:
break;
}
return instruct;
}
public static void main(String[] args) {
System.out.println(getTrafficInstruct(Signal.RED));
}
}
Java 中提供了两个方便操作 enum 的工具类——EnumSet 和 EnumMap。
EnumSet 是枚举类型的高性能 Set 实现。它要求放入它的枚举常量必须属于同一枚举类型。
主要接口:
public static void main(String[] args) {
EnumSet<ColorEnum> enums = EnumSet.allOf(ColorEnum.class);
for (ColorEnum colorEnum : enums) {
System.out.println(colorEnum.getValue());
}
}
EnumMap 是专门为枚举类型量身定做的 Map 实现。虽然使用其它的 Map 实现(如 HashMap)也能完成枚举类型实例到值得映射,但是使用 EnumMap 会更加高效:它只能接收同一枚举类型的实例作为键值,并且由于枚举类型实例的数量相对固定并且有限,所以 EnumMap 使用数组来存放与枚举类型对应的值。这使得 EnumMap 的效率非常高。
主要接口:
枚举完美地解决了之前通过常量来表示离散量所带来的问题,大大加强了程序的可读性、易用性和可维护性,并且在此基础之上又进行了扩展,使之可以像类一样去使用,更是为Java对离散量的表示上升了一个台阶。因此,如果在Java中需要表示诸如颜色、方式、类别、状态等等数目有限、形式离散、表达又极为明确的量,应当尽量舍弃常量表示的做法,而将枚举作为首要的选择。