Java 探索 Enum 实现

本贴最后更新于 1959 天前,其中的信息可能已经东海扬尘

动手写一个 Enum 类
package com.guihuo.api.java.lang;

public enum MyEnum { 
    A,
    B; 
}
查看字节码

在命令行中执行以下命令

javap MyEnum.class

得到以下代码

public final class com.guihuo.api.java.lang.MyEnum extends java.lang.Enum<com.guihuo.api.java.lang.MyEnum> {
  public static final com.guihuo.api.java.lang.MyEnum A;
  public static final com.guihuo.api.java.lang.MyEnum B;
  public static com.guihuo.api.java.lang.MyEnum[] values();
  public static com.guihuo.api.java.lang.MyEnum valueOf(java.lang.String);
  static {};
}
一些收获
  • enum 最终还是会编译成 class,同时继承 Enum。
  • 枚举中的每一项都会转成枚举类下的静态常量。
  • 通过查看完整字节码,可以发现 values 调用的是 常量池中 $VALUES 的 clone()方法。
  • 通过查看完整字节码,可以发现 valueOf 调用的是 Enum 下的 valueOf 方法。
查看完整字节码

在命令行中执行以下命令 查看 Java 编译器生成完整字节码

javap -verbose MyEnum.class

得到以下代码

Classfile /C:/Users/guihuo/Desktop/MyEnum.class
  Last modified 2018-12-6; size 988 bytes
  MD5 checksum 63cd6f3e2f55e64ba5028a8874b4b405
  Compiled from "MyEnum.java"
public final class com.guihuo.api.java.lang.MyEnum extends java.lang.Enum<com.guihuo.api.java.lang.MyEnum>
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
Constant pool:
   #1 = Fieldref           #4.#36         // com/guihuo/api/java/lang/MyEnum.$VALUES:[Lcom/guihuo/api/java/lang/MyEnum;
   #2 = Methodref          #37.#38        // "[Lcom/guihuo/api/java/lang/MyEnum;".clone:()Ljava/lang/Object;
   #3 = Class              #17            // "[Lcom/guihuo/api/java/lang/MyEnum;"
   #4 = Class              #39            // com/guihuo/api/java/lang/MyEnum
   #5 = Methodref          #12.#40        // java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
   #6 = Methodref          #12.#41        // java/lang/Enum."<init>":(Ljava/lang/String;I)V
   #7 = String             #13            // A
   #8 = Methodref          #4.#41         // com/guihuo/api/java/lang/MyEnum."<init>":(Ljava/lang/String;I)V
   #9 = Fieldref           #4.#42         // com/guihuo/api/java/lang/MyEnum.A:Lcom/guihuo/api/java/lang/MyEnum;
  #10 = String             #15            // B
  #11 = Fieldref           #4.#43         // com/guihuo/api/java/lang/MyEnum.B:Lcom/guihuo/api/java/lang/MyEnum;
  #12 = Class              #44            // java/lang/Enum
  #13 = Utf8               A
  #14 = Utf8               Lcom/guihuo/api/java/lang/MyEnum;
  #15 = Utf8               B
  #16 = Utf8               $VALUES
  #17 = Utf8               [Lcom/guihuo/api/java/lang/MyEnum;
  #18 = Utf8               values
  #19 = Utf8               ()[Lcom/guihuo/api/java/lang/MyEnum;
  #20 = Utf8               Code
  #21 = Utf8               LineNumberTable
  #22 = Utf8               valueOf
  #23 = Utf8               (Ljava/lang/String;)Lcom/guihuo/api/java/lang/MyEnum;
  #24 = Utf8               LocalVariableTable
  #25 = Utf8               name
  #26 = Utf8               Ljava/lang/String;
  #27 = Utf8               <init>
  #28 = Utf8               (Ljava/lang/String;I)V
  #29 = Utf8               this
  #30 = Utf8               Signature
  #31 = Utf8               ()V
  #32 = Utf8               <clinit>
  #33 = Utf8               Ljava/lang/Enum<Lcom/guihuo/api/java/lang/MyEnum;>;
  #34 = Utf8               SourceFile
  #35 = Utf8               MyEnum.java
  #36 = NameAndType        #16:#17        // $VALUES:[Lcom/guihuo/api/java/lang/MyEnum;
  #37 = Class              #17            // "[Lcom/guihuo/api/java/lang/MyEnum;"
  #38 = NameAndType        #45:#46        // clone:()Ljava/lang/Object;
  #39 = Utf8               com/guihuo/api/java/lang/MyEnum
  #40 = NameAndType        #22:#47        // valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
  #41 = NameAndType        #27:#28        // "<init>":(Ljava/lang/String;I)V
  #42 = NameAndType        #13:#14        // A:Lcom/guihuo/api/java/lang/MyEnum;
  #43 = NameAndType        #15:#14        // B:Lcom/guihuo/api/java/lang/MyEnum;
  #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 com.guihuo.api.java.lang.MyEnum A;
    descriptor: Lcom/guihuo/api/java/lang/MyEnum;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  public static final com.guihuo.api.java.lang.MyEnum B;
    descriptor: Lcom/guihuo/api/java/lang/MyEnum;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

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

  public static com.guihuo.api.java.lang.MyEnum valueOf(java.lang.String);
    descriptor: (Ljava/lang/String;)Lcom/guihuo/api/java/lang/MyEnum;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: ldc           #4                  // class com/guihuo/api/java/lang/MyEnum
         2: aload_0
         3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
         6: checkcast     #4                  // class com/guihuo/api/java/lang/MyEnum
         9: areturn
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  name   Ljava/lang/String;

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=4, locals=0, args_size=0
         0: new           #4                  // class com/guihuo/api/java/lang/MyEnum
         3: dup
         4: ldc           #7                  // String A
         6: iconst_0
         7: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
        10: putstatic     #9                  // Field A:Lcom/guihuo/api/java/lang/MyEnum;
        13: new           #4                  // class com/guihuo/api/java/lang/MyEnum
        16: dup
        17: ldc           #10                 // String B
        19: iconst_1
        20: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
        23: putstatic     #11                 // Field B:Lcom/guihuo/api/java/lang/MyEnum;
        26: iconst_2
        27: anewarray     #4                  // class com/guihuo/api/java/lang/MyEnum
        30: dup
        31: iconst_0
        32: getstatic     #9                  // Field A:Lcom/guihuo/api/java/lang/MyEnum;
        35: aastore
        36: dup
        37: iconst_1
        38: getstatic     #11                 // Field B:Lcom/guihuo/api/java/lang/MyEnum;
        41: aastore
        42: putstatic     #1                  // Field $VALUES:[Lcom/guihuo/api/java/lang/MyEnum;
        45: return
      LineNumberTable:
        line 13: 0
        line 12: 26
}
Signature: #33                          // Ljava/lang/Enum<Lcom/guihuo/api/java/lang/MyEnum;>;
SourceFile: "MyEnum.java"
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • someone

    蒋哥牛逼

  • wenandlu

    那感觉枚举就没什么意义了,自己写个类,放些静态最终变量,也是一样的效果

  • someone

    😄 😄