基本的枚举定义

enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性,存放在 java.lang 包中。

定义:

  1. package top.twolovelypig;
  2. public enum EnumMain {
  3. MON, TUE, WED, THU, FRI, SAT, SUN;
  4. }

输出枚举值代码:

  1. package top.twolovelypig;
  2. public class Test {
  3. public static void main(String[] args) {
  4. for (EnumMain e : EnumMain.values()) {
  5. System.out.println(e.toString());
  6. }
  7. }
  8. }

enum对象基本方法

  • int compareTo(E o) 该方法用来比较枚举与指定对象的顺序

    1. public static void main(String[] args) {
    2. //值为6,表明SUN在MON后面六位
    3. System.out.println(EnumMain.SUN.compareTo(EnumMain.MON));
    4. //值为-2,表明tue比thu小两位(tue在thu前面两位)
    5. System.out.println(EnumMain.TUE.compareTo(EnumMain.THU));
    6. //值为0,表示二者是一样的
    7. System.out.println(EnumMain.MON.compareTo(EnumMain.MON));
    8. }
  • 需要注意的是这里比较的值是有大小和正负的,不是说后面的与前面的相比结果就是1,也有可能是其他正数,具体结果是几就需要看后面的枚举是在前面的枚举后几位

  • Class<E> ``**getDeclaringClass**()返回与枚举常量的枚举类型相对应的class对象

    1. package top.twolovelypig;
    2. public class Test {
    3. public static void main(String[] args) {
    4. EnumMain enumMain = EnumMain.FRI;
    5. System.out.println("getDeclaringClass(): " + enumMain.getDeclaringClass().getName());
    6. }
    7. }
  • 输出的结果是类的全路径: getDeclaringClass(): top.twolovelypig.EnumMain

  • String name()返回此枚举常量的名称

    1. public static void main(String[] args) {
    2. EnumMain enumMain = EnumMain.FRI;
    3. System.out.println("name(): " + enumMain.name());
    4. }
  • 输出结果是: name(): FRI

  • int ordinal() 返回枚举常量的序数(初始常量序数为0)

    1. public static void main(String[] args) {
    2. EnumMain enumMain = EnumMain.FRI;
    3. System.out.println("ordinal(): " + enumMain.ordinal());
    4. }
  • 输出结果是4,因为FRI是第五个,初始常量序数是0,所以输出结果是4

  • String toString() 返回枚举常量的名称

给enum自定义属性和方法(带参数的enum)

enum

  1. package top.twolovelypig;
  2. public enum EnumMain {
  3. MON("星期一", 1),
  4. TUE("星期二", 2),
  5. WED("星期三", 3),
  6. THU("星期四", 4),
  7. FRI("星期五", 5),
  8. SAT("星期六", 6),
  9. SUN("星期天",7);
  10. // 成员变量
  11. private String name;
  12. private int index;
  13. // 构造方法
  14. private EnumMain(String name, int index) {
  15. this.name = name;
  16. this.index = index;
  17. }
  18. // 普通方法 根据index获取name
  19. public static String getNameByIndex(int index) {
  20. for (EnumMain c : EnumMain.values()) {
  21. if (c.getIndex() == index) {
  22. return c.name;
  23. }
  24. }
  25. return null;
  26. }
  27. // 普通方法 根据index获取name
  28. public static int getIndexByName(String name) {
  29. for (EnumMain c : EnumMain.values()) {
  30. if (c.name.equals(name)) {
  31. return c.index;
  32. }
  33. }
  34. return 0;
  35. }
  36. // get set 方法
  37. public String getName() {
  38. return name;
  39. }
  40. public void setName(String name) {
  41. this.name = name;
  42. }
  43. public int getIndex() {
  44. return index;
  45. }
  46. public void setIndex(int index) {
  47. this.index = index;
  48. }
  49. }

上面代码中getIndexByName()方法中需要注意c.namec.getName()的区别,c.name获取的是中文比如星期三,而c.getName()的结果是FRI

测试代码,根据名称获取索引,根据索引获取名称等:

  1. package top.twolovelypig;
  2. public class Test {
  3. public static void main(String[] args) {
  4. EnumMain enumMain = EnumMain.FRI;
  5. //普通get方法 输出结果是5
  6. System.out.println(enumMain.getIndex());
  7. //普通getName()方法 输出结果是星期五
  8. System.out.println(enumMain.getName());
  9. //根据index获取name 输出结果是星期三
  10. System.out.println(EnumMain.getNameByIndex(3));
  11. //根据name获取index 输出结果是3
  12. System.out.println(EnumMain.getIndexByName("星期三"));
  13. }
  14. }

对枚举的理解

可能不好理解的就是上面具有参数的枚举,其实只需要记住一点,java中一切皆对象,可以把枚举页当做一个类,这样来看的话上面的代码可以写成下面这样:

  1. package top.twolovelypig;
  2. public class EnumMain {
  3. // 成员变量
  4. private String name;
  5. private int index;
  6. // 构造方法
  7. private EnumMain(String name, int index) {
  8. this.name = name;
  9. this.index = index;
  10. }
  11. // get set 方法
  12. public String getName() {
  13. return name;
  14. }
  15. public void setName(String name) {
  16. this.name = name;
  17. }
  18. public int getIndex() {
  19. return index;
  20. }
  21. public void setIndex(int index) {
  22. this.index = index;
  23. }
  24. }

对于上面的类比较好理解吧,就是具有两个属性而已,然后呢就是一个私有构造方法以及get/set方法。而对于枚举中的这些声明

  1. MON("星期一", 1),
  2. TUE("星期二", 2),
  3. WED("星期三", 3),
  4. THU("星期四", 4),
  5. FRI("星期五", 5),
  6. SAT("星期六", 6),
  7. SUN("星期天",7);

其实就是该枚举类的对象,每一个声明都是一个对象,也就是这里其实有七个对象,此时简单理解枚举与类的区别就是枚举中对象是数量固定,相当于在一开始就实例化了几个固定的对象而已。然后后面哪些根据key获取name,以及根据name获取key都是自己加的一些方法而已。

enumMap

以下内容来自《java编程的逻辑》这本书。

如果需要一个Map的实现类,并且建的类型为枚举类型,可以使用HashMap,但应该使用一个专门的实现类EnumMap。因为枚举类型有两个特征:

  • 枚举所有可能的值时有限的并且是预定义的
  • 所有的枚举值有一个顺序

这两个特征可以更为高效的实现Map接口。

案例

比如有一批关于衣服的记录,想要通过尺寸统计衣服的数量,定义一个简单的枚举类Size;都表示衣服的尺寸。

Size枚举:

  1. public enum Size{
  2. SMALL, MEDIUM, LARGE
  3. }

Clothes

  1. class Clothes{
  2. String id;
  3. Size size;
  4. //get与set
  5. }

按尺寸统计数量:

  1. public static Map<Size, Integer> countBySize(List<Clothes> clothes){
  2. Map<Size, Integer> map = new EnumMap(Size.class);
  3. for(Clothes c : clothes){
  4. Size size = c.getSize();
  5. Integer count = map.get(size);
  6. if(count != null){
  7. map.put(size, count+1);
  8. }else{
  9. map.put(size, 1);
  10. }
  11. }
  12. }

需要注意EnumMap的构造方法

  1. Map<Size, Integer> map = new EnumMap(Size.class);

EnumMap需要传递一个类型信息,Size.class表示枚举类Size的运行时信息,需要这个参数是因为EnumMap要知道具体的枚举类是什么。

测试代码:

  1. List<Clothes> clothes = Arrays.asList(
  2. new Clothes[]{
  3. new Clothes("c001", Size.SMALL),
  4. new Clothes("c002", Size.MEDIUM),
  5. new Clothes("c003", Size.LARGE),
  6. new Clothes("c004", Size.SMALL),
  7. new Clothes("c005", Size.MEDIUM),
  8. new Clothes("c006", Size.LARGE)
  9. }
  10. );
  11. System.out.println(countBySize(clothes));

需要说明的是,EnumMap是保证顺序的,输出是按照键在枚举中的顺序的。

enum的另外两个构造方法

除了以上介绍的构造方法,EnumMap还有两个构造方法,可以接受一个键值匹配的EnumMap或普通Map,如下所示:

  1. public EnumMap(EnumMap<K, ? extends V> m)
  2. public EnumMap(Map<K, ? extends V> m)

比如:

  1. Map<Size,Integer> hashMap = new HashMap<>();
  2. hashMap.put(Size.LARGE, 2);
  3. hashMap.put(Size.SMALL, 1);
  4. Map<Size, Integer> enumMap = new EnumMap<>(hashMap);