Java枚举实现原理

编译枚举EnumImplMechanism.java,通过jad反编译获得EnumImplMechanism.jad文件

D:\>javac EnumImplMechanism.java
D:\>jad EnumImplMechanism.class
Parsing EnumImplMechanism.class... Generating EnumImplMechanism.jad

通过jad文件发现枚举最终被反编译成为一个继承自 java.lang.Enum不可变(final) 类,并生成默认构造函数 EnumImplMechanism(String name, int ordinal) ,默认构造函数调用父类构造函数 Enum(String name, int ordinal)

  • 通过 static 方法块在类加载时初始化各个实例,name 为实例的名称,根据实例的定义顺序为 ordinal 设置默认值,调用默认构造函数,所以 枚举为饿汉式加载
  • 各个实例初始化以后放入数组 $VALUES 中供接口 values() 访问
  • valueOf 调用 java.lang.Enum 根据指定name获取 EnumImplMechanism.classClass常量池 中相应的实例。
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   EnumImplMechanism.java


public final class EnumImplMechanism extends Enum
{

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

    public static EnumImplMechanism valueOf(String s)
    {
        return (EnumImplMechanism)Enum.valueOf(EnumImplMechanism, s);
    }

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

    public static final EnumImplMechanism INSTANCE_1;
    public static final EnumImplMechanism INSTANCE_2;
    public static final EnumImplMechanism INSTANCE_3;
    private static final EnumImplMechanism $VALUES[];

    static 
    {
        INSTANCE_1 = new EnumImplMechanism("INSTANCE_1", 0);
        INSTANCE_2 = new EnumImplMechanism("INSTANCE_2", 1);
        INSTANCE_3 = new EnumImplMechanism("INSTANCE_3", 2);
        $VALUES = (new EnumImplMechanism[] {
            INSTANCE_1, INSTANCE_2, INSTANCE_3
        });
    }
}

java.lang.Enum::valueOf
根据指定name获取当前枚举Class常量池中相应的实例(查看javap反编译结果),例如当前枚举中INSTANCE_1对应常量池中的实例:

#9 = Fieldref           #4.#41         // EnumImplMechanism.INSTANCE_1:LEnumImplMechanism;
    public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                String name) {
        T result = enumType.enumConstantDirectory().get(name);
        if (result != null)
            return result;
        if (name == null)
            throw new NullPointerException("Name is null");
        throw new IllegalArgumentException(
            "No enum constant " + enumType.getCanonicalName() + "." + name);
    }

EnumImplMechanism自定义构造函数,编译后发现仍会调用父类默认构造函数,自定义构造器参数附加在默认构造器参数之后。

// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   EnumImplMechanism.java


public final class EnumImplMechanism extends Enum
{

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

    public static EnumImplMechanism valueOf(String s)
    {
        return (EnumImplMechanism)Enum.valueOf(EnumImplMechanism, s);
    }

    private EnumImplMechanism(String s, int i, String s1)
    {
        super(s, i);
        description = s1;
    }

    public String getDescription()
    {
        return description;
    }

    public static final EnumImplMechanism INSTANCE_1;
    public static final EnumImplMechanism INSTANCE_2;
    public static final EnumImplMechanism INSTANCE_3;
    private String description;
    private static final EnumImplMechanism $VALUES[];

    static 
    {
        INSTANCE_1 = new EnumImplMechanism("INSTANCE_1", 0, "This is first instance");
        INSTANCE_2 = new EnumImplMechanism("INSTANCE_2", 1, "This is second instance");
        INSTANCE_3 = new EnumImplMechanism("INSTANCE_3", 2, "This is third instance");
        $VALUES = (new EnumImplMechanism[] {
            INSTANCE_1, INSTANCE_2, INSTANCE_3
        });
    }
}

javap -v EnumImplMechanism.class 反编译结果

D:\>javap -v EnumImplMechanism.class
Classfile /D:/EnumImplMechanism.class
  Last modified 2019-3-29; size 906 bytes
  MD5 checksum 7664bb3e640684514d5bf3ca888e7eef
  Compiled from "EnumImplMechanism.java"
public final class EnumImplMechanism extends java.lang.Enum<EnumImplMechanism>
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
Constant pool:
   #1 = Fieldref           #4.#35         // EnumImplMechanism.$VALUES:[LEnumImplMechanism;
   #2 = Methodref          #36.#37        // "[LEnumImplMechanism;".clone:()Ljava/lang/Object;
   #3 = Class              #20            // "[LEnumImplMechanism;"
   #4 = Class              #38            // EnumImplMechanism
   #5 = Methodref          #14.#39        // java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
   #6 = Methodref          #14.#40        // java/lang/Enum."<init>":(Ljava/lang/String;I)V
   #7 = String             #15            // INSTANCE_1
   #8 = Methodref          #4.#40         // EnumImplMechanism."<init>":(Ljava/lang/String;I)V
   #9 = Fieldref           #4.#41         // EnumImplMechanism.INSTANCE_1:LEnumImplMechanism;
  #10 = String             #17            // INSTANCE_2
  #11 = Fieldref           #4.#42         // EnumImplMechanism.INSTANCE_2:LEnumImplMechanism;
  #12 = String             #18            // INSTANCE_3
  #13 = Fieldref           #4.#43         // EnumImplMechanism.INSTANCE_3:LEnumImplMechanism;
  #14 = Class              #44            // java/lang/Enum
  #15 = Utf8               INSTANCE_1
  #16 = Utf8               LEnumImplMechanism;
  #17 = Utf8               INSTANCE_2
  #18 = Utf8               INSTANCE_3
  #19 = Utf8               $VALUES
  #20 = Utf8               [LEnumImplMechanism;
  #21 = Utf8               values
  #22 = Utf8               ()[LEnumImplMechanism;
  #23 = Utf8               Code
  #24 = Utf8               LineNumberTable
  #25 = Utf8               valueOf
  #26 = Utf8               (Ljava/lang/String;)LEnumImplMechanism;
  #27 = Utf8               <init>
  #28 = Utf8               (Ljava/lang/String;I)V
  #29 = Utf8               Signature
  #30 = Utf8               ()V
  #31 = Utf8               <clinit>
  #32 = Utf8               Ljava/lang/Enum<LEnumImplMechanism;>;
  #33 = Utf8               SourceFile
  #34 = Utf8               EnumImplMechanism.java
  #35 = NameAndType        #19:#20        // $VALUES:[LEnumImplMechanism;
  #36 = Class              #20            // "[LEnumImplMechanism;"
  #37 = NameAndType        #45:#46        // clone:()Ljava/lang/Object;
  #38 = Utf8               EnumImplMechanism
  #39 = NameAndType        #25:#47        // valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
  #40 = NameAndType        #27:#28        // "<init>":(Ljava/lang/String;I)V
  #41 = NameAndType        #15:#16        // INSTANCE_1:LEnumImplMechanism;
  #42 = NameAndType        #17:#16        // INSTANCE_2:LEnumImplMechanism;
  #43 = NameAndType        #18:#16        // INSTANCE_3:LEnumImplMechanism;
  #44 = Utf8               java/lang/Enum
  #45 = Utf8               clone
  #46 = Utf8               ()Ljava/lang/Object;
  #47 = Utf8               (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
{
  public static final EnumImplMechanism INSTANCE_1;
    descriptor: LEnumImplMechanism;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  public static final EnumImplMechanism INSTANCE_2;
    descriptor: LEnumImplMechanism;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  public static final EnumImplMechanism INSTANCE_3;
    descriptor: LEnumImplMechanism;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  public static EnumImplMechanism[] values();
    descriptor: ()[LEnumImplMechanism;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: getstatic     #1                  // Field $VALUES:[LEnumImplMechanism;
         3: invokevirtual #2                  // Method "[LEnumImplMechanism;".clone:()Ljava/lang/Object;
         6: checkcast     #3                  // class "[LEnumImplMechanism;"
         9: areturn
      LineNumberTable:
        line 2: 0

  public static EnumImplMechanism valueOf(java.lang.String);
    descriptor: (Ljava/lang/String;)LEnumImplMechanism;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: ldc           #4                  // class EnumImplMechanism
         2: aload_0
         3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
         6: checkcast     #4                  // class EnumImplMechanism
         9: areturn
      LineNumberTable:
        line 2: 0

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=4, locals=0, args_size=0
         0: new           #4                  // class EnumImplMechanism
         3: dup
         4: ldc           #7                  // String INSTANCE_1
         6: iconst_0
         7: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
        10: putstatic     #9                  // Field INSTANCE_1:LEnumImplMechanism;
        13: new           #4                  // class EnumImplMechanism
        16: dup
        17: ldc           #10                 // String INSTANCE_2
        19: iconst_1
        20: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
        23: putstatic     #11                 // Field INSTANCE_2:LEnumImplMechanism;
        26: new           #4                  // class EnumImplMechanism
        29: dup
        30: ldc           #12                 // String INSTANCE_3
        32: iconst_2
        33: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
        36: putstatic     #13                 // Field INSTANCE_3:LEnumImplMechanism;
        39: iconst_3
        40: anewarray     #4                  // class EnumImplMechanism
        43: dup
        44: iconst_0
        45: getstatic     #9                  // Field INSTANCE_1:LEnumImplMechanism;
        48: aastore
        49: dup
        50: iconst_1
        51: getstatic     #11                 // Field INSTANCE_2:LEnumImplMechanism;
        54: aastore
        55: dup
        56: iconst_2
        57: getstatic     #13                 // Field INSTANCE_3:LEnumImplMechanism;
        60: aastore
        61: putstatic     #1                  // Field $VALUES:[LEnumImplMechanism;
        64: return
      LineNumberTable:
        line 3: 0
        line 4: 13
        line 5: 26
        line 2: 39
}
Signature: #32                          // Ljava/lang/Enum<LEnumImplMechanism;>;
SourceFile: "EnumImplMechanism.java"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值