解密JDK8 枚举

写一个枚举类

1
2
3
4
5
6
public enum Season {
SPRING,
SUMMER,
AUTUMN,
WINTER
}

然后我们使用javac编译上面的类,得到class文件

然后,我们利用反编译的方法来看看字节码文件究竟是什么.这里使用的工具是javap的简单命令,先列举一下这个Season下的全部元素.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
Classfile /C:/Season.class
Last modified 2016-12-8; size 956 bytes
MD5 checksum 7f6dfb988d182327a1a73ee986a9d3fa
Compiled from "Season.java"
public final class cn.redis.model.Season extends java.lang.Enum<cn.redis.model.S
eason>
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
Constant pool:
#1 = Fieldref #4.#38 // cn/redis/model/Season.$VALUES:[Lcn/
redis/model/Season;
#2 = Methodref #39.#40 // "[Lcn/redis/model/Season;".clone:()
Ljava/lang/Object;
#3 = Class #23 // "[Lcn/redis/model/Season;"
#4 = Class #41 // cn/redis/model/Season
#5 = Methodref #16.#42 // java/lang/Enum.valueOf:(Ljava/lang/
Class;Ljava/lang/String;)Ljava/lang/Enum;
#6 = Methodref #16.#43 // java/lang/Enum."<init>":(Ljava/lang
/String;I)V
#7 = String #17 // SPRING
#8 = Methodref #4.#43 // cn/redis/model/Season."<init>":(Lja
va/lang/String;I)V
#9 = Fieldref #4.#44 // cn/redis/model/Season.SPRING:Lcn/re
dis/model/Season;
#10 = String #19 // SUMMER
#11 = Fieldref #4.#45 // cn/redis/model/Season.SUMMER:Lcn/re
dis/model/Season;
#12 = String #20 // AUTUMN
#13 = Fieldref #4.#46 // cn/redis/model/Season.AUTUMN:Lcn/re
dis/model/Season;
#14 = String #21 // WINTER
#15 = Fieldref #4.#47 // cn/redis/model/Season.WINTER:Lcn/re
dis/model/Season;
#16 = Class #48 // java/lang/Enum
#17 = Utf8 SPRING
#18 = Utf8 Lcn/redis/model/Season;
#19 = Utf8 SUMMER
#20 = Utf8 AUTUMN
#21 = Utf8 WINTER
#22 = Utf8 $VALUES
#23 = Utf8 [Lcn/redis/model/Season;
#24 = Utf8 values
#25 = Utf8 ()[Lcn/redis/model/Season;
#26 = Utf8 Code 大专栏  解密JDK8 枚举
#27 = Utf8 LineNumberTable
#28 = Utf8 valueOf
#29 = Utf8 (Ljava/lang/String;)Lcn/redis/model/Season;
#30 = Utf8 <init>
#31 = Utf8 (Ljava/lang/String;I)V
#32 = Utf8 Signature
#33 = Utf8 ()V
#34 = Utf8 <clinit>
#35 = Utf8 Ljava/lang/Enum<Lcn/redis/model/Season;>;
#36 = Utf8 SourceFile
#37 = Utf8 Season.java
#38 = NameAndType #22:#23 // $VALUES:[Lcn/redis/model/Season;
#39 = Class #23 // "[Lcn/redis/model/Season;"
#40 = NameAndType #49:#50 // clone:()Ljava/lang/Object;
#41 = Utf8 cn/redis/model/Season
#42 = NameAndType #28:#51 // valueOf:(Ljava/lang/Class;Ljava/lan
g/String;)Ljava/lang/Enum;
#43 = NameAndType #30:#31 // "<init>":(Ljava/lang/String;I)V
#44 = NameAndType #17:#18 // SPRING:Lcn/redis/model/Season;
#45 = NameAndType #19:#18 // SUMMER:Lcn/redis/model/Season;
#46 = NameAndType #20:#18 // AUTUMN:Lcn/redis/model/Season;
#47 = NameAndType #21:#18 // WINTER:Lcn/redis/model/Season;
#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 cn.redis.model.Season SPRING;
descriptor: Lcn/redis/model/Season;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
public static final cn.redis.model.Season SUMMER;
descriptor: Lcn/redis/model/Season;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
public static final cn.redis.model.Season AUTUMN;
descriptor: Lcn/redis/model/Season;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
public static final cn.redis.model.Season WINTER;
descriptor: Lcn/redis/model/Season;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
public static cn.redis.model.Season[] values();
descriptor: ()[Lcn/redis/model/Season;
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: getstatic #1 // Field $VALUES:[Lcn/redis/model/
Season;
3: invokevirtual #2 // Method "[Lcn/redis/model/Season
;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[Lcn/redis/model/Season;
"
9: areturn
LineNumberTable:
line 3: 0
public static cn.redis.model.Season valueOf(java.lang.String);
descriptor: (Ljava/lang/String;)Lcn/redis/model/Season;
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: ldc #4 // class cn/redis/model/Season
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(
Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 // class cn/redis/model/Season
9: areturn
LineNumberTable:
line 3: 0
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=4, locals=0, args_size=0
0: new #4 // class cn/redis/model/Season
3: dup
4: ldc #7 // String SPRING
6: iconst_0
7: invokespecial #8 // Method "<init>":(Ljava/lang/Str
ing;I)V
10: putstatic #9 // Field SPRING:Lcn/redis/model/Se
ason;
13: new #4 // class cn/redis/model/Season
16: dup
17: ldc #10 // String SUMMER
19: iconst_1
20: invokespecial #8 // Method "<init>":(Ljava/lang/Str
ing;I)V
23: putstatic #11 // Field SUMMER:Lcn/redis/model/Se
ason;
26: new #4 // class cn/redis/model/Season
29: dup
30: ldc #12 // String AUTUMN
32: iconst_2
33: invokespecial #8 // Method "<init>":(Ljava/lang/Str
ing;I)V
36: putstatic #13 // Field AUTUMN:Lcn/redis/model/Se
ason;
39: new #4 // class cn/redis/model/Season
42: dup
43: ldc #14 // String WINTER
45: iconst_3
46: invokespecial #8 // Method "<init>":(Ljava/lang/Str
ing;I)V
49: putstatic #15 // Field WINTER:Lcn/redis/model/Se
ason;
52: iconst_4
53: anewarray #4 // class cn/redis/model/Season
56: dup
57: iconst_0
58: getstatic #9 // Field SPRING:Lcn/redis/model/Se
ason;
61: aastore
62: dup
63: iconst_1
64: getstatic #11 // Field SUMMER:Lcn/redis/model/Se
ason;
67: aastore
68: dup
69: iconst_2
70: getstatic #13 // Field AUTUMN:Lcn/redis/model/Se
ason;
73: aastore
74: dup
75: iconst_3
76: getstatic #15 // Field WINTER:Lcn/redis/model/Se
ason;
79: aastore
80: putstatic #1 // Field $VALUES:[Lcn/redis/model/
Season;
83: return
LineNumberTable:
line 4: 0
line 5: 13
line 6: 26
line 7: 39
line 3: 52
}
Signature: #35 // Ljava/lang/Enum<Lcn/redis/model/Seaso
n;>;
SourceFile: "Season.java"

从上反编译结果可知

  • java代码中的Season转换成了继承自的java.lang.enum的类
  • 既然隐式继承自java.lang.enum,也就意味java代码中,Season不能再继承其他的类
  • Season被标记成了final,意味着它不能被继承
  • 静态块static {}; 0~52为实例化SPRING, SUMMER, AUTUMN, WINTER
  • 53~83为创建Season[]数组$VALUES,并将上面的四个对象放入数组的操作.
  • 8: invokevirtual #4 在switch-case中,还是将Enum转成了int值(通过调用Enum.oridinal()方法)
原文地址:https://www.cnblogs.com/lijianming180/p/12326281.html