Enum枚举详解

前言:关于枚举类也就是enum关键字相信大家都或多或少听过,要知道的是枚举类在公司工作中用的是非常普遍的,那么关于如何使用枚举类以及枚举的实现原理到底是怎样的,请接着往下看。


1.什么是枚举

在数学和计算机科学理论中,一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。这两种类型经常(但不总是)重叠。  是一个被命名的整型常数的集合,枚举在日常生活中很常见,例如表示星期的SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY就是一个枚举。

通俗的说,枚举就是一些有序数字(从0开始)的集合,这些数字都被取了一个名字,或者说这些数字就代表着对象的序数。

2.怎么写枚举

/**
星期的枚举类
*/
public enum Weekend{
    SUNDAY,
    MONDAY,
    TUESDAY,    
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    STARDAY;

}

3.枚举原理

枚举可以说其实就是一个普通的类,跟普通的类并不二异。我们第一次看到上面的这个枚举类

代码时可能会一脸懵,为什么大写写了几个字母然后之间用逗号隔开,这样写有锤子用啊?当时第一次接触的我也是一脸困惑。那么它到底干了什么呢,我们可以通过编译这段源代码之后,生成字节码文件反编译之后看看它到底有什么奥秘。

具体该怎么做呢?

首先在开发工具中写好这个枚举

 然后我们编译好之后找生成的.class文件所在目录

如果idea的话可以在target目录下找到该文件右击选择Open IN->Explorer就能进入到Weekend.class文件位置

 其次输入cmd进入控制命令台

 输入javap -p Weekend.class进行反编译得到结果

 我们惊喜的发现它为我们创建了一个public final class Weekend类并且继承了java.lang.Enum类

 而SUNDAY这样的就是生成的一个个静态变量对象,

除此之外还有values数组以及valuesOf方法。valuesOf()方法其实都是重写了父类Enum类的方法.

最后为我们创建了一个私有的构造函数,说明枚举类是不能再通过new来创建一个实例化对象的。

其实javap这个自带的反编译程序并没有十分完整的展示这个类。这里我利用jad.exe反编译工具,真正完整的类应该是这样的。

public final class Weekend extends Enum
{

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

    public static Weekend valueOf(String name)
    {
        return (Weekend)Enum.valueOf(com/zhong/basictest/Weekend, name);
    }

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

    public static final Weekend SUNDAY;
    public static final Weekend MONDAY;
    public static final Weekend TUESDAY;
    public static final Weekend WEDNESDAY;
    public static final Weekend THURSDAY;
    public static final Weekend FRIDAY;
    public static final Weekend STARDAY;
    private static final Weekend $VALUES[];

    static 
    {
        SUNDAY = new Weekend("SUNDAY", 0);
        MONDAY = new Weekend("MONDAY", 1);
        TUESDAY = new Weekend("TUESDAY", 2);
        WEDNESDAY = new Weekend("WEDNESDAY", 3);
        THURSDAY = new Weekend("THURSDAY", 4);
        FRIDAY = new Weekend("FRIDAY", 5);
        STARDAY = new Weekend("STARDAY", 6);
        $VALUES = (new Weekend[] {
            SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, STARDAY
        });
    }
}

看到这里相信小伙伴应该能够解开中的疑团了吧,原来每个变量名都是一个对象,再进一步了解一下Enum这个类,会发现的是我们创建每一个枚举对象的同时会把变量名和0,1这样的序数依次赋值给父类,序数是随着变量创建而增长的,也就是说父类的变量保存了我们的变量名称和序数。

我们可以用调用父类的方法name()和ordinal()取得它的名称和序数。

同样我们回到正轨,这原来就是一个普通的类嘛,于是乎我们可以可以像正常对象那样,创建有参构造(修饰符不能为public编译器会报错,目的是不让我们能实例化对象),定义变量等操作,亦或是创建方法等等。致此,枚举类也就拨云见日了,相信再遇到枚举类应该能够轻松拿下了吧,同样反编译这个手段好好利用也可以助于我们对代码的解读。

4.枚举的作用

最后,枚举类的作用有哪些呢?其实枚举类作用是简化我们创建一些不变的静态变量,可以使代码变得更加简洁,同样使用枚举类也可以避免被Class类的newInstance()方法创建对象,可以将其利用于单例模式中,保证对象的安全。


版权声明:本文为qq_45698467原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。