枚举,enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性,存放在 java.lang 包中。
创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类)。枚举类型符合通用模式 Class Enum<E extends Enum<E>>,而 E 表示枚举类型的名称。枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal) 构造函数中,在这里,每个值的名称都被转换成一个字符串,并且序数设置表示了此设置被创建的顺序。
比如创建以下SeasonEnum枚举:
public enum SeasonEnum{ spring, summer, autumn, winter; } 这段代码实际调用了4次Enum(String name, int ordinal): new Enum<SeasonEnum>("spring",0); new Enum<SeasonEnum>("summer",1); new Enum<SeasonEnum>("autumn",2); new Enum<SeasonEnum>("winter",3);int compareTo(E o) 比较此枚举与指定对象的顺序。
Class<E> getDeclaringClass() 返回与此枚举常量的枚举类型相对应的 Class 对象。
String name() 返回此枚举常量的名称,在其枚举声明中对其进行声明。
int ordinal() 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。
String toString()
返回枚举常量的名称,它包含在声明中。
static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) 返回带指定名称的指定枚举类型的枚举常量。
具体看下列demo:
/** * Created by flh on 2017/8/31. */ public class TestEnum { //普通的枚举 public enum ColorEnum{ red, green, yellow, blue; } //枚举像普通的类一样可以添加属性和方法,可以为它添加静态和非静态的属性或方法 public enum SeasonEnum{ spring, summer, autumn, winter; private final static String value = "spring"; public static SeasonEnum method(){ if("wqh".equals(value)) return spring; else return winter; } } //实现带有构造器的枚举 public enum Gender{ //通过括号赋值,而且必须带有一个参构造器和一个属性跟方法,否则编译出错 //赋值必须都赋值或都不赋值,不能一部分赋值一部分不赋值;如果不赋值则不能写构造器,赋值编译也出错 MAN("MAN"), WOMAN("WOAMN"); private final String value; //构造器默认也只能是private, 从而保证构造函数只能在内部使用 private Gender(String value){ this.value = value; } public String getValue(){ return value; } } //实现带有抽象方法的枚举 public enum OrderState{ /** 已取消 */ CANCEL {public String getName(){return "已取消";}}, /** 待审核 */ WAITCONFIRM {public String getName(){return "待审核";}}, /** 等待付款 */ WAITPAYMENT {public String getName(){return "等待付款";}}, /** 正在配货 */ ADMEASUREPRODUCT {public String getName(){return "正在配货";}}, /** 等待发货 */ WAITDELIVER {public String getName(){return "等待发货";}}, /** 已发货 */ DELIVERED {public String getName(){return "已发货";}}, /** 已收货 */ RECEIVED {public String getName(){return "已收货";}}; public abstract String getName(); } public static void main(String[] args) { //遍历枚举 for(ColorEnum color : ColorEnum.values()){ System.out.println(color); } //通过赋值get for(Gender gender : Gender.values()){ System.out.println(gender.value); } //枚举默认实现java.lang.Comparable接口 System.out.println(ColorEnum.red.compareTo(ColorEnum.green));//-1 //使用抽象方法 for(OrderState order : OrderState.values()){ System.out.println(order.getName()); } //获取枚举的个数 System.out.println("OrderState枚举中的值有"+OrderState.values().length+"个"); //获取枚举的索引位置,默认从0开始 System.out.println(Gender.MAN.ordinal());//0 System.out.println(Gender.WOMAN.ordinal());//1 } }java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的key是enum类型,而value则可以是任意类型。
enum 的语法结构尽管和class 的语法不一样,但是经过编译器编译之后产生的是一个class文件。该class文件经过反编译可以看到实际上是生成了一个类,该类继承了java.lang.Enum<E>。所以,实际上 enum 就是一个 class,只不过 java 编译器帮我们做了语法的解析和编译而已。
具体的原理参考博客: java枚举类型的实现原理
这篇博客的总结:
枚举本质上是通过普通的类来实现的,只是编译器为我们进行了处理。每个枚举类型都继承自java.lang.Enum,并自动添加了values和valueOf方法。而每个枚举常量是一个静态常量字段,使用内部类实现,该内部类继承了枚举类。所有枚举常量都通过静态代码块来进行初始化,即在类加载期间就初始化。另外通过把clone、readObject、writeObject这三个方法定义为final的,同时实现是抛出相应的异常。这样保证了每个枚举类型及枚举常量都是不可变的。可以利用枚举的这两个特性来实现线程安全的单例。
注意:enum 不能使用 extends 关键字继承其他类,因为 enum 已经继承了 java.lang.Enum(java是单一继承)。但是可以实现接口
demo:
public interface Behaviour { void print(); String getInfo(); } public enum Color implements Behaviour{ RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this.name = name; this.index = index; } //接口方法 @Override public String getInfo() { return this.name; } //接口方法 @Override public void print() { System.out.println(this.index+":"+this.name); } }