Java 枚举

枚举概述

什么是枚举

枚举是一个被命名的整型常数的集合,枚举在日常生活中很常见,例如表示星期的 SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY 就是一个枚举。通俗来说,枚举就是一个对象的所有可能取值的集合

来自:维基百科 枚举

普通代码实现枚举

使用常量类来代替枚举类

class WeekDay {
    public static final Integer MONDAY = 1;
    public static final Integer TUESDAY = 2;
    public static final Integer WEDNESDAY = 3;
    public static final Integer THURSDAY = 4;
    public static final Integer FRIDAY = 5;
    public static final Integer SATURDAY = 6;
    public static final Integer SUNDAY = 7;
}

需要传入指定内容的方法

public class Employee {

    /**
     * 指定员工在哪一天休息
     */
    private Integer restDay;

    public Integer getRestDay() {
        return restDay;
    }

    public void setRestDay(Integer restDay) {
        if (restDay > 7 || restDay < 1){
            throw new RuntimeException("完蛋");
        }
        this.restDay = restDay;
    }
}

可以在内容方法中限定传入的数值,但是数值的合理性无法交给编译器去判断,会增大代码复杂度。

测试类

public static void main(String[] args) {
    Employee employee = new Employee();
    employee.setRestDay(43);
}

枚举类是如何解决方法传入内容检查的?

枚举类详解

示例代码

枚举类

public enum WeekDayEnum {

    MONDAY(1, "星期一"),
    TUESDAY(2, "星期二"),
    WEDNESDAY(3, "星期三"),
    THURSDAY(4, "星期四"),
    FRIDAY(5, "星期五"),
    SATURDAY(6, "星期六"),
    SUNDAY(7, "星期日"),
    ;

    private int code;
    private String desc;

    WeekDayEnum(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public int getCode() {
        return code;
    }

    public String getDesc() {
        return desc;
    }
}
  • 枚举类结尾使用 Enum 命名
  • 内容使用大写字母,单词之间使用下划线分隔
  • 构造方法可带参数可不带

接收枚举方法

public class WorkDay {

    private WeekDayEnum workDay;

    public void setWorkDay(WeekDayEnum workDay){
        this.workDay = workDay;
    }
}

测试方法

public static void main(String[] args) {
    WorkDay workDay = new WorkDay();
    workDay.setWorkDay(WeekDayEnum.MONDAY);
}

由于方法只接收指定的枚举类型,因此只有指定枚举类中的元素时编译器会通过。

源码解析

反编译枚举类内容

// Decompiled by DJ v3.12.12.100 Copyright 2015 Atanas Neshkov  Date: 2022/1/6 9:53:24
// Home Page:  http://www.neshkov.com/dj.html - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   WeekDayEnum.java

package com.mochen.advance.enums.real;

public final class WeekDayEnum extends Enum
{

    public static WeekDayEnum[] values()
    {
        return (WeekDayEnum[])$VALUES.clone();
    }

    public static WeekDayEnum valueOf(String name)
    {
        return (WeekDayEnum)Enum.valueOf(com/mochen/advance/enums/real/WeekDayEnum, name);
    }

    private WeekDayEnum(String s, int i, int code, String desc)
    {
        super(s, i);
        this.code = code;
        this.desc = desc;
    }

    public int getCode()
    {
        return code;
    }

    public String getDesc()
    {
        return desc;
    }

    public static final WeekDayEnum MONDAY;
    public static final WeekDayEnum TUESDAY;
    public static final WeekDayEnum WEDNESDAY;
    public static final WeekDayEnum THURSDAY;
    public static final WeekDayEnum FRIDAY;
    public static final WeekDayEnum SATURDAY;
    public static final WeekDayEnum SUNDAY;
    private int code;
    private String desc;
    private static final WeekDayEnum $VALUES[];

    static 
    {
        MONDAY = new WeekDayEnum("MONDAY", 0, 1, "\u661F\u671F\u4E00");
        TUESDAY = new WeekDayEnum("TUESDAY", 1, 2, "\u661F\u671F\u4E8C");
        WEDNESDAY = new WeekDayEnum("WEDNESDAY", 2, 3, "\u661F\u671F\u4E09");
        THURSDAY = new WeekDayEnum("THURSDAY", 3, 4, "\u661F\u671F\u56DB");
        FRIDAY = new WeekDayEnum("FRIDAY", 4, 5, "\u661F\u671F\u4E94");
        SATURDAY = new WeekDayEnum("SATURDAY", 5, 6, "\u661F\u671F\u516D");
        SUNDAY = new WeekDayEnum("SUNDAY", 6, 7, "\u661F\u671F\u65E5");
        $VALUES = (new WeekDayEnum[] {
            MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
        });
    }
}

反编译后发现所谓的枚举类就是一个继承了 Enum 类的枚举类,会自动生成两个方法 values() 获取所有的枚举元素, valueOf() 根据枚举元素名称获取到指定的元素。枚举类的本质其实就是一组静态常量对象,在 static 方法块中所有的元素进行初始化,可以发现在编写源码时设置的参数是两个,但在反编译后参数变成了四个,第一个是元素的名称,第二个是序号从0开始,接下来就是我们设置的参数。可以看到在构造函数中前两个参数交给了父类的构造函数去处理,在父类中也是简单的将这两个参数储存。

image

这是一个构造函数有参数的枚举类,那么无参的枚举类是什么样子呢?

  • 源码
public enum NoParamEnum {

    HELLO,
    WORLD,
    MY,
    NAME,
    IS,
    LXC,
    ;

    NoParamEnum(){}
}
  • 反编译
// Decompiled by DJ v3.12.12.100 Copyright 2015 Atanas Neshkov  Date: 2022/1/6 10:38:42
// Home Page:  http://www.neshkov.com/dj.html - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   NoParamEnum.java

package com.mochen.advance.enums.real;


public final class NoParamEnum extends Enum
{

    public static NoParamEnum[] values()
    {
        return (NoParamEnum[])$VALUES.clone();
    }

    public static NoParamEnum valueOf(String name)
    {
        return (NoParamEnum)Enum.valueOf(com/mochen/advance/enums/real/NoParamEnum, name);
    }

    private NoParamEnum(String s, int i)
    {
        super(s, i);
    }

    public static final NoParamEnum HELLO;
    public static final NoParamEnum WORLD;
    public static final NoParamEnum MY;
    public static final NoParamEnum NAME;
    public static final NoParamEnum IS;
    public static final NoParamEnum LXC;
    private static final NoParamEnum $VALUES[];

    static 
    {
        HELLO = new NoParamEnum("HELLO", 0);
        WORLD = new NoParamEnum("WORLD", 1);
        MY = new NoParamEnum("MY", 2);
        NAME = new NoParamEnum("NAME", 3);
        IS = new NoParamEnum("IS", 4);
        LXC = new NoParamEnum("LXC", 5);
        $VALUES = (new NoParamEnum[] {
            HELLO, WORLD, MY, NAME, IS, LXC
        });
    }
}

可以看到原理并没有变化,只是在声明枚举元素的时候可以将括号省略。

同时,也可以使用自动生成的两个方法来获取到枚举类的信息。

WeekDayEnum[] values = WeekDayEnum.values();
for (WeekDayEnum value : values) {
    System.out.println(value);
}
System.out.println(WeekDayEnum.valueOf("MONDAY"));
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
MONDAY
posted @   陌尘Ya  阅读(75)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示