enum 枚举

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

定义

创建枚举类型使用 enum 关键字,创建的类型都是 java.lang.Enum(抽象类) 类的子类。枚举类型符合通用模式 Class Enum<E extends Enum<E>>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<EnumTest>("MON",0);
new Enum<EnumTest>("TUE",1);
new Enum<EnumTest>("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<E> 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 extends Enum<T>> T valueOf(Class<T> 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<Week> weekSet = EnumSet.allOf(Week.class);
for (Week w : weekSet) {
    System.out.println(w);
}

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

原理

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

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);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容