关于Enum的再次理解

167 阅读4分钟
原文链接: mp.weixin.qq.com

问:enum 算不算基本数据类型答:不算,enum是引用类型。

Java中的基本数据类型只有8种,分别是byte、short、int、long、float、double、char、boolean

在 Java5之后新增的 Enum属于引用类型,跟 String一样也是属于类。好奇的同学可能有疑问,既然说 enum是引用类型,为何在使用的时候没有见到类呢?

enum的使用场景

我们先来看一个简单的enum使用场景,

public class DayDemo {    public enum Day {      MONDAY,      TUESDAY,      WEDNESDAY,      THURSDAY    }    public static void main(String[] args) {    }}

这里面只定义了一个枚举类型 Day,通过枚举定义了周一到周四四种类型,后续我们使用的时候就可以直接用 Day.MONDAY 这样的方式来使用枚举值了。

为什么说枚举是类

在这代码里没有声明类,也没用其他的引用,那么来看看编译后的结果

$ ls'DayDemo$Day.class'   DayDemo.class   DayDemo.java

可以看到多了一个叫 DayDemo$Day.class的类出来,从 class文件可以看出, 枚举 Day编译成了一个类,从这里可以断定虽然我们没有定义这个类,但是编译器会把枚举作为类进行编译,从某种角度上来说 enum是一种语法糖,现在来看一下 class文件的构造,

public final class DayDemo$Day extends java.lang.Enum<DayDemo$Day> {  public static final DayDemo$Day MONDAY;  public static final DayDemo$Day TUESDAY;  public static final DayDemo$Day WEDNESDAY;  public static final DayDemo$Day THURSDAY;  public static DayDemo$Day[] values();    Code:       0: getstatic     #1                  // Field $VALUES:[LDayDemo$Day;       3: invokevirtual #2                  // Method "[LDayDemo$Day;".clone:()Ljava/lang/Object;       6: checkcast     #3                  // class "[LDayDemo$Day;"       9: areturn  public static DayDemo$Day valueOf(java.lang.String);    Code:       0: ldc           #4                  // class DayDemo$Day       2: aload_0       3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;       6: checkcast     #4                  // class DayDemo$Day       9: areturn  static {};    Code:       0: new           #4                  // class DayDemo$Day       3: dup       4: ldc           #7                  // String MONDAY       6: iconst_0       7: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V      10: putstatic     #9                  // Field MONDAY:LDayDemo$Day;      13: new           #4                  // class DayDemo$Day      16: dup      17: ldc           #10                 // String TUESDAY      19: iconst_1      20: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V      23: putstatic     #11                 // Field TUESDAY:LDayDemo$Day;      26: new           #4                  // class DayDemo$Day      29: dup      30: ldc           #12                 // String WEDNESDAY      32: iconst_2      33: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V      36: putstatic     #13                 // Field WEDNESDAY:LDayDemo$Day;      39: new           #4                  // class DayDemo$Day      42: dup      43: ldc           #14                 // String THURSDAY      45: iconst_3      46: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V      49: putstatic     #15                 // Field THURSDAY:LDayDemo$Day;      52: iconst_4      53: anewarray     #4                  // class DayDemo$Day      56: dup      57: iconst_0      58: getstatic     #9                  // Field MONDAY:LDayDemo$Day;      61: aastore      62: dup      63: iconst_1      64: getstatic     #11                 // Field TUESDAY:LDayDemo$Day;      67: aastore      68: dup      69: iconst_2      70: getstatic     #13                 // Field WEDNESDAY:LDayDemo$Day;      73: aastore      74: dup      75: iconst_3      76: getstatic     #15                 // Field THURSDAY:LDayDemo$Day;      79: aastore      80: putstatic     #1                  // Field $VALUES:[LDayDemo$Day;      83: return}

如果上面的代码不够简洁易懂的话可以看看下面翻译后的代码,这只翻译 static代码段,其他的像 values和 valueOf都比较简单,

static    {        //实例化枚举实例        MONDAY = new Day("MONDAY", 0);        TUESDAY = new Day("TUESDAY", 1);        WEDNESDAY = new Day("WEDNESDAY", 2);        THURSDAY = new Day("THURSDAY", 3);        $VALUES = (new Day[] {            MONDAY, TUESDAY, WEDNESDAY, THURSDAY        });    }

总结

把这段代码和上面反编译的结果一起看的话就可以明白,枚举类型在编译后会作为一个类生成,编译器会帮我们插入 values和 valueOf 两个方法,同时生成 final的常量,在生成的静态代码段里会实例化好对应的枚举实例,换句话说,我们所定义的每个枚举类,最终都会在它里面生成对应的静态常量,而常量的值就是我们所定义的值的String串。