字节码分析Java 枚举 之 通用遍历

Java 中枚举是常用的变成方式,枚举也有其一定的特殊性,以下是一个简单的枚举类。JAVA 编译器会对每一个枚举类生成一个Class类。

1
2
3
4
5
public enum Color {
white,
red,
black
}

以下是Color枚举的字节码信息,从中我们可以得知Color 自动继承了Enum,Enum 中包含了枚举常用的方法。

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
public final enum com/Color extends java/lang/Enum  {

// compiled from: Color.java

// access flags 0x4019
public final static enum Lcom/Color; white

// access flags 0x4019
public final static enum Lcom/Color; red

// access flags 0x4019
public final static enum Lcom/Color; black

// access flags 0x101A
private final static synthetic [Lcom/Color; ENUM$VALUES

// access flags 0x8
static <clinit>()V
L0
LINENUMBER 4 L0
NEW com/Color
DUP
LDC "white"
ICONST_0
INVOKESPECIAL com/Color.<init> (Ljava/lang/String;I)V
PUTSTATIC com/Color.white : Lcom/Color;
L1
LINENUMBER 5 L1
NEW com/Color
DUP
LDC "red"
ICONST_1
INVOKESPECIAL com/Color.<init> (Ljava/lang/String;I)V
PUTSTATIC com/Color.red : Lcom/Color;
L2
LINENUMBER 6 L2
NEW com/Color
DUP
LDC "black"
ICONST_2
INVOKESPECIAL com/Color.<init> (Ljava/lang/String;I)V
PUTSTATIC com/Color.black : Lcom/Color;
L3
LINENUMBER 3 L3
ICONST_3
ANEWARRAY com/Color
DUP
ICONST_0
GETSTATIC com/Color.white : Lcom/Color;
AASTORE
DUP
ICONST_1
GETSTATIC com/Color.red : Lcom/Color;
AASTORE
DUP
ICONST_2
GETSTATIC com/Color.black : Lcom/Color;
AASTORE
PUTSTATIC com/Color.ENUM$VALUES : [Lcom/Color;
RETURN
MAXSTACK = 4
MAXLOCALS = 0

// access flags 0x2
private <init>(Ljava/lang/String;I)V
L0
LINENUMBER 3 L0
ALOAD 0
ALOAD 1
ILOAD 2
INVOKESPECIAL java/lang/Enum.<init> (Ljava/lang/String;I)V
RETURN
L1
LOCALVARIABLE this Lcom/Color; L0 L1 0
MAXSTACK = 3
MAXLOCALS = 3

// access flags 0x9
public static values()[Lcom/Color;
L0
LINENUMBER 1 L0
GETSTATIC com/Color.ENUM$VALUES : [Lcom/Color;
DUP
ASTORE 0
ICONST_0
ALOAD 0
ARRAYLENGTH
DUP
ISTORE 1
ANEWARRAY com/Color
DUP
ASTORE 2
ICONST_0
ILOAD 1
INVOKESTATIC java/lang/System.arraycopy (Ljava/lang/Object;ILjava/lang/Object;II)V
ALOAD 2
ARETURN
MAXSTACK = 5
MAXLOCALS = 3

// access flags 0x9
public static valueOf(Ljava/lang/String;)Lcom/Color;
L0
LINENUMBER 1 L0
LDC Lcom/Color;.class
ALOAD 0
INVOKESTATIC java/lang/Enum.valueOf (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
CHECKCAST com/Color
ARETURN
MAXSTACK = 2
MAXLOCALS = 1
}

public static values()[Lcom/Color; 是编译器自动添加的方法,用于获取所有的枚举, 这个方法是在 Color 中的,并不是继承得来的
可以使用反射的方式遍历任意的枚举,当然也可以用于其他的处理。

1
2
3
4
5
6
public static void test (Class<?> eum ) throws Exception {
Enum[] evs = (Enum[]) eum.getDeclaredMethod("values", null).invoke(null, null);
for(Enum e : evs){
System.out.println(e);
}
}