1.自定义一个枚举类型Color.java
public enum Color {
RED,BLUE,YELLOW
}
2.javac编译Color.java,生成Color.class。javac的时候记得添加-g选项才会生成局部变量表。
javac -g Color.java
3.javap反编译Color.class,重定向到Color.txt
-v 输出详细信息
-p 不设置-p则不输出private类型变量和方法以及内部类的信息
javap -v -p Color.class > Color.txt
4.Color.txt内容如下
Classfile /C:/workspace/test/src/main/java/Color.class
Last modified 2019-12-13; size 885 bytes
MD5 checksum 5eb4ad1bb3162939cfda9b83c768e64d
Compiled from "Color.java"
public final class Color extends java.lang.Enum<Color>
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
Constant pool:
#1 = Fieldref #4.#39 // Color.$VALUES:[LColor;
#2 = Methodref #40.#41 // "[LColor;".clone:()Ljava/lang/Object;
#3 = Class #20 // "[LColor;"
#4 = Class #42 // Color
#5 = Methodref #14.#43 // java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
#6 = Methodref #14.#44 // java/lang/Enum."<init>":(Ljava/lang/String;I)V
#7 = String #15 // RED
#8 = Methodref #4.#44 // Color."<init>":(Ljava/lang/String;I)V
#9 = Fieldref #4.#45 // Color.RED:LColor;
#10 = String #17 // BLUE
#11 = Fieldref #4.#46 // Color.BLUE:LColor;
#12 = String #18 // YELLOW
#13 = Fieldref #4.#47 // Color.YELLOW:LColor;
#14 = Class #48 // java/lang/Enum
#15 = Utf8 RED
#16 = Utf8 LColor;
#17 = Utf8 BLUE
#18 = Utf8 YELLOW
#19 = Utf8 $VALUES
#20 = Utf8 [LColor;
#21 = Utf8 values
#22 = Utf8 ()[LColor;
#23 = Utf8 Code
#24 = Utf8 LineNumberTable
#25 = Utf8 valueOf
#26 = Utf8 (Ljava/lang/String;)LColor;
#27 = Utf8 LocalVariableTable
#28 = Utf8 name
#29 = Utf8 Ljava/lang/String;
#30 = Utf8 <init>
#31 = Utf8 (Ljava/lang/String;I)V
#32 = Utf8 this
#33 = Utf8 Signature
#34 = Utf8 ()V
#35 = Utf8 <clinit>
#36 = Utf8 Ljava/lang/Enum<LColor;>;
#37 = Utf8 SourceFile
#38 = Utf8 Color.java
#39 = NameAndType #19:#20 // $VALUES:[LColor;
#40 = Class #20 // "[LColor;"
#41 = NameAndType #49:#50 // clone:()Ljava/lang/Object;
#42 = Utf8 Color
#43 = NameAndType #25:#51 // valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
#44 = NameAndType #30:#31 // "<init>":(Ljava/lang/String;I)V
#45 = NameAndType #15:#16 // RED:LColor;
#46 = NameAndType #17:#16 // BLUE:LColor;
#47 = NameAndType #18:#16 // YELLOW:LColor;
#48 = Utf8 java/lang/Enum
#49 = Utf8 clone
#50 = Utf8 ()Ljava/lang/Object;
#51 = Utf8 (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
{
public static final Color RED;
descriptor: LColor;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
public static final Color BLUE;
descriptor: LColor;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
public static final Color YELLOW;
descriptor: LColor;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
private static final Color[] $VALUES;
descriptor: [LColor;
flags: ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
public static Color[] values();
descriptor: ()[LColor;
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: getstatic #1 // Field $VALUES:[LColor;
3: invokevirtual #2 // Method "[LColor;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[LColor;"
9: areturn
LineNumberTable:
line 5: 0
public static Color valueOf(java.lang.String);
descriptor: (Ljava/lang/String;)LColor;
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: ldc #4 // class Color
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 // class Color
9: areturn
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 name Ljava/lang/String;
private Color();
descriptor: (Ljava/lang/String;I)V
flags: ACC_PRIVATE
Code:
stack=3, locals=3, args_size=3
0: aload_0
1: aload_1
2: iload_2
3: invokespecial #6 // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V
6: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 7 0 this LColor;
Signature: #34 // ()V
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=4, locals=0, args_size=0
0: new #4 // class Color
3: dup
4: ldc #7 // String RED
6: iconst_0
7: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #9 // Field RED:LColor;
13: new #4 // class Color
16: dup
17: ldc #10 // String BLUE
19: iconst_1
20: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
23: putstatic #11 // Field BLUE:LColor;
26: new #4 // class Color
29: dup
30: ldc #12 // String YELLOW
32: iconst_2
33: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
36: putstatic #13 // Field YELLOW:LColor;
39: iconst_3
40: anewarray #4 // class Color
43: dup
44: iconst_0
45: getstatic #9 // Field RED:LColor;
48: aastore
49: dup
50: iconst_1
51: getstatic #11 // Field BLUE:LColor;
54: aastore
55: dup
56: iconst_2
57: getstatic #13 // Field YELLOW:LColor;
60: aastore
61: putstatic #1 // Field $VALUES:[LColor;
64: return
LineNumberTable:
line 6: 0
line 5: 39
}
Signature: #36 // Ljava/lang/Enum<LColor;>;
SourceFile: "Color.java"
5. 手动反编译的代码如下
public final class Color extends Enum<Color> {
private static final Color RED;
private static final Color BLUE;
private static final Color YELLOW;
private static final Color[] $VALUES;
static {
RED = new Color("RED", 0);
BLUE = new Color("BLUE", 1);
YELLOW = new Color("YELLOW", 2);
$VALUES = new Color[3];
$VALUES[0] = RED;
$VALUES[1] = BLUE;
$VALUES[2] = YELLOW;
}
private Color(String name, int ordinal) {
super(name, ordinal);
}
public static Color[] values(){
return $VALUES.clone();
}
public static Color valueOf(String name){
return Enum.valueOf(Color.class, name);
}
}
编译器不允许直接继承Enum,所以会提示Classes cannot directly extend 'java.lang.Enum'
6.下面对Color类的字节码进行分析,如果不感兴趣,或者对字节码不懂的,可以不往下看。
6.1 类信息
大括号前面的,是Color类的一些摘要信息。
public final class Color extends java.lang.Enum<Color>
表明enum Color.java在编译后生成了一个类Color,且Color继承了java.lang.Enum<Color>,该类是final类型,所以枚举类都是不可以继承的。
大括号里面,包含了Color类编译后的字段和方法,下面我们来分析Color类编译后生成了哪些字段和方法
6.2 枚举变量
public static final Color RED;
descriptor: LColor;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
public static final Color BLUE;
descriptor: LColor;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
public static final Color YELLOW;
descriptor: LColor;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
可以看到 RED,BLUE, YELLOW 枚举变量,在编译后就是Color类的一个实例。
6.3 values()方法
private static final Color[] $VALUES;
descriptor: [LColor;
flags: ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
public static Color[] values();
descriptor: ()[LColor;
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: getstatic #1 // Field $VALUES:[LColor;
3: invokevirtual #2 // Method "[LColor;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[LColor;"
9: areturn
LineNumberTable:
line 5: 0
编译后,Color中生成了一个私有的$VALUES变量,存储了所以了Color变量(RED,BLUE,YELLOW),且变量顺序和声明顺序一样。自动生成的values()方法会返回$VALUES。
6.4 valueOf()方法
public static Color valueOf(java.lang.String);
descriptor: (Ljava/lang/String;)LColor;
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: ldc #4 // class Color
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 // class Color
9: areturn
生成的valueOf(String)方法,会调用Enum.valueOf(Class,String)方法返回同名Color实例。
6.5 构造方法
private Color();
descriptor: (Ljava/lang/String;I)V
flags: ACC_PRIVATE
Code:
stack=3, locals=3, args_size=3
0: aload_0
1: aload_1
2: iload_2
3: invokespecial #6 // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V
6: return
枚举的构造方法都是私有的,是不能在外部调用。
6.6 static静态块
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=4, locals=0, args_size=0
0: new #4 // class Color
3: dup
4: ldc #7 // String RED
6: iconst_0
7: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #9 // Field RED:LColor;
13: new #4 // class Color
16: dup
17: ldc #10 // String BLUE
19: iconst_1
20: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
23: putstatic #11 // Field BLUE:LColor;
26: new #4 // class Color
29: dup
30: ldc #12 // String YELLOW
32: iconst_2
33: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
36: putstatic #13 // Field YELLOW:LColor;
39: iconst_3
40: anewarray #4 // class Color
43: dup
44: iconst_0
45: getstatic #9 // Field RED:LColor;
48: aastore
49: dup
50: iconst_1
51: getstatic #11 // Field BLUE:LColor;
54: aastore
55: dup
56: iconst_2
57: getstatic #13 // Field YELLOW:LColor;
60: aastore
61: putstatic #1 // Field $VALUES:[LColor;
64: return
在静态块中,创建了所有枚举变量的实例,以及$VALUES 数组。