Java 探索 Enum 实现

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

动手写一个 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 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3201 引用 • 8216 回帖 • 1 关注

相关帖子

欢迎来到这里!

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

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

    蒋哥牛逼

  • wenandlu

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

  • someone

    😄 😄