enum 枚举

enum (enumeration), 是 JDK 1.5 中引入的新特性,在 java.lang 包中。

定义

创建枚举类型使用 enum 关键字,创建的类型都是 java.lang.Enum(抽象类) 类的子类。枚举类型符合通用模式 Class Enum>E 表示枚举类型的名称。枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal)构造函数中,在这里,每个值的名称都被转换成一个字符串,并且序数设置表示了此设置被创建的顺序。

public enum Week{
    MON, TUE, WED, THU, FRI, SAT, SUN;
 } 

// 内部调用了7次 Enum(String name, int ordinal):
new Enum("MON",0);
new Enum("TUE",1);
new Enum("WED",2);
    ... ...
  1. 枚举类是特殊的class,有构造器、方法和数据域,被final修饰,不可被继承;
  2. 枚举值MON, TUE...都是Week类型的静态常量(public static final 修饰),故通常全部大写。
// 获取实例
Week w = Week.MON; 

使用

一. 自定义方法、覆盖枚举的方法

自定义方法时必须在enum实例序列最后添加分号。同时Java 要求必须先定义 enum 实例.

enum Week {
    MON(2016, 12, 12), TUE(2016, 12, 13), WED(2016, 12, 14), THU(2016, 12, 15), 
    FRI(2016, 12, 16), SUN(2016, 12, 17), SUN(2016, 12, 18); 

    //自定义数据域 (get、set 封装)
    private int year; 
    private int mouth;
    private int day;

    // 构造枚举值
    private Week (int year, int mouth, int day){ 
        this.year = year;
        this.mouth = mouth;
        this.day = day; 
    }

    // 自定义方法
    public String getDate(int day) { 
        for (Week w : Week.values()) { // 遍历
            if (w.getDay() == day) { 
                return toString();
            } 
        } 
        return null; 
    }

    //覆盖方法  
    @Override 
    public String toString() { 
         return w.year + "年" + w.mouth + "月" + w.day + "日" ;
    }  
}

注意:

  1. 构造器只在构造枚举值时被调用;
  2. 构造器只能私有private,不允许public修饰。保证了外部代码无法构造新枚举类的实例,因为枚举值是public static final的常量。 但枚举类的方法和数据域允许外部访问。
// 错误写法
Week week = new Week(2017, 1, 1);

// 正确写法
Week week = Week.MON;
System.out.println(week.getDate());

二. switch 操作

public void change() {

    Week week = Week.WED;
    switch (week) { 
         case MON: 
             week = Week.MON; 
             break; 
         case TUE: 
             week = Week.TUE; 
             break; 
         case WED: 
             week = Week.WED; 
             break;
           ……
}

三. 实现接口

枚举继承java.lang.Enum类。Java 不支持多继承,所以枚举对象不能继承其它类。

public interface Behaviour { 
    void print(); 
    String getDayOfMouth(); 
} 

enum Week {
    MON(2016, 12, 12), TUE(2016, 12, 13), WED(2016, 12, 14), THU(2016, 12, 15), 
    FRI(2016, 12, 16), SUN(2016, 12, 17), SUN(2016, 12, 18); 

    // 成员变量 (get、set 封装)
    private int year; 
    private int mouth;
    private int day;

    // 构造方法
    private Week (int year, int mouth, int day){ 
        this.year = year;
        this.mouth = mouth;
        this.day = day; 
    }

    // 接口方法
    @Override
    public String getDayOfMouth(int day) { 
        return this.day;
    }

    // 接口方法
    @Override 
    public String print() { 
        System.out.println(w.year + "年" + w.mouth + "月" + w.day + "日"); 
    }  

四. 接口组织枚举

public interface Animal { 

    enum Water implements Animal { 
        SHARK, DOLPHIN, WHALE
    } 

    enum Land implements Animal { 
        DOG, CAT, PIG, WOLF, TIGER
    } 
} 

五. 方法

继承于Enum的方法。

  1. int compareTo(E o)
    比较此枚举与指定对象的顺序(Enum实现了java.lang.Comparable接口)。返回两个枚举值的顺序之差。枚举必须属于同一个枚举类,否则抛出ClassCastException()异常。
// MON, TUE, WED, THU, FRI, SUN, SUN
Week.MON.compareTo(Week.WED);  // 结果 -2
Week.WED.compareTo(Week.MON);  // 结果 2
  1. final boolean equals(Object other)
    比较两个枚举类对象的引用。
  2. Class getDeclaringClass()
    返回与此枚举常量的枚举类型相对应的 Class 对象。
Week week = Week.MON;
System.out.println(week.getDeclaringClass().getName());
// 输出结果:com.enumtest.test.Week;
  1. String name()
    返回此枚举常量的名称,在其枚举声明中对其进行声明。
  2. int ordinal()
    返回枚举常量在枚举类中的次序(初始常量序数为 0)。
Week.MON.ordinal();  // 结果 0
Week.WED.ordinal();  // 结果 2
  1. String toString()
    返回枚举常量的名称。
Week w = Week.MON;
System.out.println(w);//返回结果: MON
  1. static > T valueOf(Class enumType, String name)
    返回带指定名称的指定枚举类型的枚举常量,与toString()方法相对应。
Week.valueOf("MON");  // 结果 Week.MON
  1. values()
    静态方法,返回一个包含全部枚举值的数组。
Week weeks = Week.values();
for(Week w:weeks){
    System.out.print(w + ",");
}
//返回结果:MON, TUE, WED, THU, FRI, SUN, SUN

五. 枚举集合

java.util.EnumSet:保证集合中的元素不重复。
java.util.EnumMapkeyenum类型,value可以是任意类型。

// EnumSet的使用
EnumSet weekSet = EnumSet.allOf(Week.class);
for (Week w : weekSet) {
    System.out.println(w);
}

// EnumMap的使用
EnumMap weekMap = new EnumMap(Week.class);
weekMap.put(Week.MON, "星期一");
weekMap.put(Week.TUE, "星期二");
// ... ...
for (Iterator> iter = weekMap.entrySet().iterator(); 
    iter.hasNext();) {
        Entry entry = iter.next();
        System.out.println(entry.getKey().name() + ":" + entry.getValue());
}

原理

enum 的语法结构和 class 的不同,但编译器编译之后生成一个class文件。经反编译,可知该class文件生成了一个继承java.lang.Enum的类。

public class com.dev.test.Week extends java.lang.Enum{
    public static final com.dev.test.Week MON;
    public static final com.dev.test.Week TUE;
    public static final com.dev.test.Week WED;
    public static final com.dev.test.Week THU;
    public static final com.dev.test.Week FRI;
    public static final com.dev.test.Week SAT;
    public static final com.dev.test.Week SUN;
    static {};
    public int getValue();
    public boolean isRest();
    public static com.dev.test.Week[] values();
    public static com.dev.test.Week valueOf(java.lang.String);
    com.dev.test.Week(java.lang.String, int, int, com.dev.test.Week);
}

你可能感兴趣的:(enum 枚举)