java enum枚举的使用详情(实例与原理分析)

一、原始的接口定义常量

public interface IConstants {
    String MON = "Mon";
    String TUE = "Tue";
    String WED = "Wed";
    String THU = "Thu";
    String FRI = "Fri";
    String SAT = "Sat";
    String SUN = "Sun";
}

二、语法(定义)

创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类)。枚举类型符合通用模式 Class Enum

package com.sihai.test;
/**
 * 枚举测试类
 * @author  
 */
public enum EnumTest {
    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);

三、遍历、switch 等常用操作

对enum进行遍历和switch的操作示例代码:

public class Test {
    public static void main(String[] args) {
        for (EnumTest e : EnumTest.values()) {
            System.out.println(e.toString());
        }

        System.out.println("----------------我是分隔线------------------");

        EnumTest test = EnumTest.TUE;
        switch (test) {
        case MON:
            System.out.println("今天是星期一");
            break;
        case TUE:
            System.out.println("今天是星期二");
            break;
        // ... ...
        default:
            System.out.println(test);
            break;
        }
    }
}

输出结果:
MON
TUE
WED
THU
FRI
SAT
SUN
—————-我是分隔线——————
今天是星期二

四、enum 对象的常用方法介绍

int compareTo(E o)
比较此枚举与指定对象的顺序。

Class getDeclaringClass()
返回与此枚举常量的枚举类型相对应的 Class 对象。

String name()
返回此枚举常量的名称,在其枚举声明中对其进行声明。

int ordinal()
返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。

String toString()
返回枚举常量的名称,它包含在声明中。

static > T valueOf(Class enumType, String name) 
          返回带指定名称的指定枚举类型的枚举常量。
public class Test {
    public static void main(String[] args) {
        EnumTest test = EnumTest.TUE;

        //compareTo(E o)
        switch (test.compareTo(EnumTest.MON)) {
        case -1:
            System.out.println("TUE 在 MON 之前");
            break;
        case 1:
            System.out.println("TUE 在 MON 之后");
            break;
        default:
            System.out.println("TUE 与 MON 在同一位置");
            break;
        }

        //getDeclaringClass()
        System.out.println("getDeclaringClass(): " + test.getDeclaringClass().getName());

        //name() 和  toString()
        System.out.println("name(): " + test.name());
        System.out.println("toString(): " + test.toString());

        //ordinal(), 返回值是从 0 开始
        System.out.println("ordinal(): " + test.ordinal());
    }
}

输出结果:
TUE 在 MON 之后
getDeclaringClass(): com.sihai.test.EnumTest
name(): TUE
toString(): TUE
ordinal(): 1
给 enum 自定义属性和方法

五、EnumSet,EnumMap 的应用

public class Test {
    public static void main(String[] args) {
        // EnumSet的使用
        EnumSet weekSet = EnumSet.allOf(EnumTest.class);
        for (EnumTest day : weekSet) {
            System.out.println(day);
        }

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

六、举例

构造方法的枚举类(构造方法有一个参数),下面是比较常用的一种方式:

/**
 * 任务状态枚举类
 * Created by sihaion 2017/4/27.
 */
public enum TaskStatusEnum {

    NotStart(0),    //未开始
    Doing(1),       //执行中
    Pause(2),       //暂停
    Completed(3),   //已完成
    Del(4),         //删除
    CutShort(5) ;   //提前结束

    private int value;
    TaskStatusEnum(int value) {
        this.value=value;
    }
    public  int getValue(){
        return  value;
    }

    /**
     * 根据value返回对应的枚举值
     * @param value
     * @return
     */
    public static TaskStatusEnum valueOf(int value) {
        switch (value) {
            case 0: return NotStart;
            case 1: return Doing;
            case 2: return Pause;
            case 3: return Completed;
            case 4: return Del;
            case 5: return CutShort;
            default: return null;
        }
    }
}

订单状态枚举类:

/**
 * 订单状体枚举类
 * Created by sihaion 2017/5/1.
 */
public enum OrderStatus {

    WaitPay(0), //等待支付
    Paid(1),    //已经支付
    Expired(2), //已经失效
    Force(3);   //已经生效

    private int value;
    OrderStatus(int value) {
        this.value=value;
    }
    public  int getValue(){
        return  value;
    }

    public static OrderStatus valueOf(int value) {
        switch (value) {
            case 0:
                return WaitPay;
            case 1:
                return Paid;
            case 2:
                return Expired;
            case 3:
                return Force;
            default:
                return null;
        }
    }
}

消息状态枚举类:

/**
 * 消息状态枚举类
 * Created by sihaion 2017/5/1.
 */
public enum MessageStatus {

    Read(1),//已读
    UnRead(0);//未读

    private int value;
    MessageStatus(int value) {
        this.value=value;
    }
    public  int getValue(){
        return  value;
    }

    public static MessageStatus valueOf(int value) {
        switch (value) {
            case 1:
                return Read;
            case 0:
                return UnRead;
            default:
                return null;
        }
    }
}

月份的枚举类:

/**
 * 月份枚举类
 * Created by sihaion 2017/5/1.
 */
public enum MonthEnum {

    Jan(1),
    Feb(2),
    Mar(3),
    Apr(4),
    May(5),
    Jun(6),
    Jul(7),
    Aug(8),
    Sep(9),
    Oct(10),
    Nov(11),
    Dec(12);

    private Integer index;

    public Integer getIndex() {
        return index;
    }

    MonthEnum(Integer index) {
        this.index = index;
    }

    /**
     * 根据索引获取对应的枚举对象
     * @param index
     * @return
     */
    public static MonthEnum getEnumTypeByIndex(Integer index) {
        MonthEnum[] values = MonthEnum.values();
        for (MonthEnum value : values) {
            if (value.getIndex() == index) {
                return value;
            }
        }
        return null;
    }
}

用法举例:

/**
 * Created by sihaion 2017/4/30.
 */
public class AppTest {
    public static void main(String[] args) {
        Integer index = MonthEnum.Apr.getIndex();
        //输出:  Apr这个枚举值对应的索引为:    4
        System.out.println("Apr这个枚举值对应的索引为:\t" + index);

        //输出:  索引4对应的枚举值为:    Apr
        MonthEnum monthEnum = MonthEnum.getEnumTypeByIndex(4);
        System.out.println("索引4对应的枚举值为:\t" + monthEnum.name());
    }
}

注意:

  • 枚举中的所有构造方法都必须是private修饰,如果不加任何修饰符,默认就是private修饰。

  • 枚举类中定义的工具方法getEnumTypeByIndex()使用static修饰,这样才能通过MonthEnum.getEnumTypeByIndex(4)的方式来调用。

枚举类的构造方法有两个参数的情况:

import java.util.HashMap;
import java.util.Map;

/**
 * 星期枚举类
 * Created by sihaion 2017/5/1.
 */
public enum WeekDayEnum {
    SUN(0, "星期日"),
    MON(1, "星期一"),
    TUE(2, "星期二"),
    WED(3, "星期三"),
    THUR(4, "星期四"),
    FRI(5, "星期五"),
    SAT(6, "星期六");

    private Integer index;
    private String key;

    WeekDayEnum(Integer index, String key) {
        this.index = index;
        this.key = key;
    }

    public String getKey() {
        return key;
    }

    public Integer getIndex() {
        return index;
    }

    /**
     * 根据枚举名称得到key
     * 比如根据"WED"得到"星期三"
     * @param name
     * @return
     */
    public static String getKeyByName(String name) {
        WeekDayEnum[] values = WeekDayEnum.values();
        for (WeekDayEnum value : values) {
            if (value.name().equals(name)) {
                return value.getKey();
            }
        }
        return null;
    }

    /**
     * 根据属性key获取属性index:
     * 比如根据 "星期三" 得到 3
     * @param key
     * @return
     */
    public static Integer getIndexByKey(String key) {
        for (WeekDayEnum weekDayEnum : WeekDayEnum.values()) {
            String k = weekDayEnum.getKey();
            if (k.equals(key)) {
                return weekDayEnum.getIndex();
            }
        }
        return null;
    }

    /**
     * 根据属性index获取属性key:
     * 比如根据 3 得到 "星期三"
     * @param index
     * @return
     */
    public static String getKeyByIndex(Integer index) {
        for (WeekDayEnum weekDayEnum : WeekDayEnum.values()) {
            Integer in = weekDayEnum.getIndex();
            if (in == index) {
                return weekDayEnum.getKey();
            }
        }
        return null;
    }

    /**
     * 根据属性index获取对应的枚举值:
     * 比如根据 3 得到枚举值 WED
     * @param index
     * @return
     */
    public static WeekDayEnum getTypeByIndex(Integer index) {
        for (WeekDayEnum value : WeekDayEnum.values()) {
            if (value.getIndex() == index) {
                return value;
            }
        }
        return null;
    }

    /**
     * 返回一个由index和key组成的map集合:
     * {0=星期日, 1=星期一, 2=星期二, 3=星期三, 4=星期四, 5=星期五, 6=星期六}
     * @return
     */
    public static Map getIndexKeyMap() {
        Map map = new HashMap<>();
        for (WeekDayEnum value : WeekDayEnum.values()) {
            Integer index = value.getIndex();
            String key = value.getKey();
            map.put(index, key);
        }
        return map;
    }
}

用法举例:

import java.util.Map;

/**
 * Created by sihaion 2017/4/30.
 */
public class AppTest {
    public static void main(String[] args) {
        Integer index = WeekDayEnum.getIndexByKey("星期日");
        System.out.println(index);//输出 0

        String key = WeekDayEnum.getKeyByIndex(0);
        System.out.println(key);//输出 星期日

        String keyByName = WeekDayEnum.getKeyByName("SAT");
        System.out.println(keyByName);//输出 星期六

        Map map = WeekDayEnum.getIndexKeyMap();
        //输出  {0=星期日, 1=星期一, 2=星期二, 3=星期三, 4=星期四, 5=星期五, 6=星期六}
        System.out.println(map);
    }
}

构造方法的参数有多个情况:

import java.util.ArrayList;
import java.util.List;

/**
 * Created by sihaion 2017/5/1.
 */
public enum WeekDayEnumX {
    SUN(0, "星期日", "Sunday"),
    MON(1, "星期一", "Monday"),
    TUE(2, "星期二", "Tuesday"),
    WED(3, "星期三", "Wednesday"),
    THUR(4, "星期四", "Thursday"),
    FRI(5, "星期五", "Friday"),
    SAT(6, "星期六", "Saturday");

    private Integer index;//索引
    private String cn;//中文表示
    private String en;//英文表示

    WeekDayEnumX(Integer index, String cn, String en) {
        this.index = index;
        this.cn = cn;
        this.en = en;
    }

    public static String getCnByIndex(Integer index) {
        WeekDayEnumX[] values = WeekDayEnumX.values();
        for (WeekDayEnumX value : values) {
            if (value.index == index) {
                return value.cn;
            }
        }
        return null;
    }

    public static String getEnByIndex(Integer index) {
        WeekDayEnumX[] values = WeekDayEnumX.values();
        for (WeekDayEnumX value : values) {
            if (value.index == index) {
                return value.en;
            }
        }
        return null;
    }

    /**
     * 获取所有的索引list
     * @return
     */
    public static List getAllIndex() {
        List list = new ArrayList<>();
        WeekDayEnumX[] values = WeekDayEnumX.values();
        for (WeekDayEnumX value : values) {
            list.add(value.index);
        }
        return list;
    }

    /**
     * 将枚举值中的所有属性封装到一个list集合中
     * @return
     */
    public static List> getAll() {
        List> lists = new ArrayList<>();
        WeekDayEnumX[] values = WeekDayEnumX.values();
        for (WeekDayEnumX value : values) {
            List elementList = new ArrayList<>();

            elementList.add(value.name());
            elementList.add(value.index);
            elementList.add(value.cn);
            elementList.add(value.en);

            lists.add(elementList);
        }

        return lists;
    }
}

用法举例:

import java.util.List;

/**
 * Created by sihaion 2017/4/30.
 */
public class AppTest {
    public static void main(String[] args) {
        List allIndex = WeekDayEnumX.getAllIndex();
        System.out.println(allIndex);//输出 [0, 1, 2, 3, 4, 5, 6]

        List> allList = WeekDayEnumX.getAll();
        for (List list : allList) {
            /**
             * 输出结果:
             * 
             * [SUN, 0, 星期日, Sunday]
             * [MON, 1, 星期一, Monday]
             * [TUE, 2, 星期二, Tuesday]
             * [WED, 3, 星期三, Wednesday]
             * [THUR, 4, 星期四, Thursday]
             * [FRI, 5, 星期五, Friday]
             * [SAT, 6, 星期六, Saturday]
             */
            System.out.println(list);
        }
    }
}

带有抽象方法的枚举类:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by sihaion 2017/5/1.
 */
public enum WeekDayEM {
    SUN {
        @Override
        public Integer getValue() {
            return 0;
        }

        @Override
        public String getKey() {
            return "星期日";
        }
    },
    MON {
        @Override
        public Integer getValue() {
            return 1;
        }

        @Override
        public String getKey() {
            return "星期一";
        }
    },
    TUE {
        @Override
        public Integer getValue() {
            return 2;
        }

        @Override
        public String getKey() {
            return "星期二";
        }
    },
    WED {
        @Override
        public Integer getValue() {
            return 3;
        }

        @Override
        public String getKey() {
            return "星期三";
        }
    },
    THU {
        @Override
        public Integer getValue() {
            return 4;
        }

        @Override
        public String getKey() {
            return "星期四";
        }
    },
    FRI {
        @Override
        public Integer getValue() {
            return 5;
        }

        @Override
        public String getKey() {
            return "星期五";
        }
    },
    SAT {
        @Override
        public Integer getValue() {
            return 6;
        }

        @Override
        public String getKey() {
            return "星期六";
        }
    };

    public abstract Integer getValue();
    public abstract String getKey();

    /**
     * 返回由key和value组成的map集合:
     * {星期二=2, 星期六=6, 星期三=3, 星期四=4, 星期五=5, 星期日=0, 星期一=1}
     * @return
     */
    public static Map getKeyValueMap() {
        HashMap map = new HashMap<>();
        WeekDayEM[] values = WeekDayEM.values();
        for (WeekDayEM value : values) {
            String k = value.getKey();
            Integer v = value.getValue();
            map.put(k, v);
        }
        return map;
    }

    /**
     * 返回由所有key组成的list集合:
     * [星期日, 星期一, 星期二, 星期三, 星期四, 星期五, 星期六]
     * @return
     */
    public static List getAllKey() {
        List keyList = new ArrayList<>();
        WeekDayEM[] values = WeekDayEM.values();
        for (WeekDayEM value : values) {
            String k = value.getKey();
            keyList.add(k);
        }
        return keyList;
    }

    /**
     * 返回由所有value组成的list集合:
     * [0, 1, 2, 3, 4, 5, 6]
     * @return
     */
    public static List getAllValue() {
        List valueList = new ArrayList<>();
        WeekDayEM[] values = WeekDayEM.values();
        for (WeekDayEM value : values) {
            Integer v = value.getValue();
            valueList.add(v);
        }
        return valueList;
    }
}

在上面的枚举类中,定义了两个抽象方法:

所以每一个枚举值(对象)都必须实现这两个抽象方法。

用法举例:

/**
 * Created by sihaion 2017/4/30.
 */
public class AppTest {
    public static void main(String[] args) {
        String key = WeekDayEM.THU.getKey();
        Integer value = WeekDayEM.THU.getValue();
        //输出  星期四, 4
        System.out.println(key + ", " + value);
    }
}

七、原理分析

enum 的语法结构尽管和 class 的语法不一样,但是经过编译器编译之后产生的是一个class文件。该class文件经过反编译可以看到实际上是生成了一个类,该类继承了java.lang.Enum。EnumTest 经过反编译(javap com.sihai.test.EnumTest 命令)之后得到的内容如下:

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

所以,实际上 enum 就是一个 class,只不过 java 编译器帮我们做了语法的解析和编译而已。

八、总结

可以把 enum 看成是一个普通的 class,它们都可以定义一些属性和方法,不同之处是:enum 不能使用 extends 关键字继承其他类,因为 enum 已经继承了 java.lang.Enum(java是单一继承)。

你可能感兴趣的:(=====,java基础,=====)