库升级时给枚举加了个常量,已经编译好的客户端会怎样?switch 是按序号还是按名字?删掉常量会炸吗?这篇用 6 个版本的枚举 jar 和同一个客户端 class 逐个验证。
类文件: ['Client$1.class', 'Client.class']
Client$1 的字段: ['static final int[] $SwitchMap$Color;', '6: putstatic #7 // Field $SwitchMap$Color:[I', '9: getstatic #7 // Field $SwitchMap$Color:[I']
Client$1 静态初始化里的关键指令(前 10 条):
0: invokestatic #1 // Method Color.values:()[LColor;
6: putstatic #7 // Field $SwitchMap$Color:[I
9: getstatic #7 // Field $SwitchMap$Color:[I
12: getstatic #13 // Field Color.RED:LColor;
15: invokevirtual #17 // Method Color.ordinal:()I
18: iconst_1
19: iastore
23: astore_0
24: getstatic #7 // Field $SwitchMap$Color:[I
27: getstatic #23 // Field Color.GREEN:LColor;
异常表条目数(每个 case 常量一个 try/catch NoSuchFieldError): 2
exprExhaustive(没有 default 的 switch 表达式)的字节码关键行:
0: getstatic #9 // Field Client$1.$SwitchMap$Color:[I
4: invokevirtual #15 // Method Color.ordinal:()I
7: iaload
8: lookupswitch { // 2
36: new #29 // class java/lang/MatchException
42: invokespecial #31 // Method java/lang/MatchException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V
45: athrow [v1]
枚举现在的常量:RED(0) GREEN(1)
stmtDefault RED→红 GREEN→绿
stmtNoDefault RED→红 GREEN→绿
exprExhaustive RED→红 GREEN→绿
exprDefault RED→红 GREEN→绿
ordinalSwitch RED→ordinal 0 GREEN→ordinal 1
[v2-新增在末尾]
枚举现在的常量:RED(0) GREEN(1) BLUE(2)
stmtDefault RED→红 GREEN→绿 BLUE→其它
stmtNoDefault RED→红 GREEN→绿 BLUE→未匹配
exprExhaustive RED→红 GREEN→绿 BLUE→MatchException
exprDefault RED→红 GREEN→绿 BLUE→其它
ordinalSwitch RED→ordinal 0 GREEN→ordinal 1 BLUE→ordinal 其它
[v3-新增在中间]
枚举现在的常量:RED(0) BLUE(1) GREEN(2)
stmtDefault RED→红 BLUE→其它 GREEN→绿
stmtNoDefault RED→红 BLUE→未匹配 GREEN→绿
exprExhaustive RED→红 BLUE→MatchException GREEN→绿
exprDefault RED→红 BLUE→其它 GREEN→绿
ordinalSwitch RED→ordinal 0 BLUE→ordinal 1 GREEN→ordinal 其它
[v4-重排]
枚举现在的常量:GREEN(0) RED(1)
stmtDefault GREEN→绿 RED→红
stmtNoDefault GREEN→绿 RED→红
exprExhaustive GREEN→绿 RED→红
exprDefault GREEN→绿 RED→红
ordinalSwitch GREEN→ordinal 0 RED→ordinal 1
[v5-删除 GREEN]
枚举现在的常量:RED(0)
stmtDefault RED→红
stmtNoDefault RED→红
exprExhaustive RED→红
exprDefault RED→红
ordinalSwitch RED→ordinal 0
[v6-重命名 GREEN→LIME]
枚举现在的常量:RED(0) LIME(1)
stmtDefault RED→红 LIME→其它
stmtNoDefault RED→红 LIME→未匹配
exprExhaustive RED→红 LIME→MatchException
exprDefault RED→红 LIME→其它
ordinalSwitch RED→ordinal 0 LIME→ordinal 1