//: enumerated/TrafficLight.java
// Enums in switch statements.
import static net.mindview.util.Print.*;
// Define an enum type:
enum Signal { GREEN, YELLOW, RED, }
public class TrafficLight {
Signal color = Signal.RED;
public void change() {
switch(color) {
// Note that you don't have to say Signal.RED
// in the case statement:
case RED: color = Signal.GREEN;
break;
case GREEN: color = Signal.YELLOW;
break;
case YELLOW: color = Signal.RED;
break;
}
}
public String toString() {
return "The traffic light is " + color;
}
public static void main(String[] args) {
TrafficLight t = new TrafficLight();
for(int i = 0; i < 7; i++) {
print(t);
t.change();
}
}
}
这是一个来自 java 编程思想的代码,我发现 out 目录还生成了一个 TrafficLight$1.class,意思生成了一个匿名内部类呢,这是因为 switchcase 吗?
TrafficLight.class 部分汇编如下:
public void change();
Code:
0: getstatic #4 // Field TrafficLight$1.$SwitchMap$Signal:[I 这里去得到匿名内部类的静态成员
3: aload_0
4: getfield #3 // Field color:LSignal;
7: invokevirtual #5 // Method Signal.ordinal:()I
10: iaload
11: tableswitch { // 1 to 3
1: 36
2: 46
3: 56
default: 63
}
TrafficLight$1.class 部分汇编如下:
class TrafficLight$1 {
static final int[] $SwitchMap$Signal; 静态成员是个 int 数组
static {};
Code:
0: invokestatic #1 // Method Signal.values:()[LSignal;
3: arraylength
4: newarray int
6: putstatic #2 // Field $SwitchMap$Signal:[I 为啥这里只有一个 putstatic,之后又三个 getstatic Field $SwitchMap$Signal:[I 呀?
9: getstatic #2 // Field $SwitchMap$Signal:[I
12: getstatic #3 // Field Signal.RED:LSignal;
15: invokevirtual #4 // Method Signal.ordinal:()I
18: iconst_1
19: iastore
20: goto 24
23: astore_0
24: getstatic #2 // Field $SwitchMap$Signal:[I
27: getstatic #6 // Field Signal.GREEN:LSignal;
30: invokevirtual #4 // Method Signal.ordinal:()I
33: iconst_2
34: iastore
35: goto 39
38: astore_0
39: getstatic #2 // Field $SwitchMap$Signal:[I
42: getstatic #7 // Field Signal.YELLOW:LSignal;
45: invokevirtual #4 // Method Signal.ordinal:()I
1
lanterboy 2020-04-05 15:26:46 +08:00
是的,这个内部类是用来存储枚举的映射表的,它记录了枚举和跳转符号的关系。实际上 case 的还是对应的数值,调用时会经过一次枚举对象到索引的转换
|
2
amiwrong123 OP @lanterboy
好吧,但是 java 汇编我看得有点迷。。 TrafficLight.class 部分汇编里,感觉没有那句 getstatic #4 // Field TrafficLight$1.$SwitchMap$Signal:[I 也一样啊。因为后面调用了 Signal 枚举实例的 ordinal 方法了就返回了一个 int 值了啊,感觉也没没用上那个匿名内部类的静态的 int 数组成员啊。 |
3
alamaya 2020-04-05 19:03:57 +08:00
@amiwrong123
你看漏了 iaload,这里是取了映射数组下标(枚举的 ordinal )的值进行入栈的,这么做是为了使用 tableswitch |