动手写一个 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"
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于