我只是被这种行为所吸引,并且在谷歌搜索时出现了这个问题。我想我会分享一些我发现的额外信息。
javac 1.5 和 1.6 每次在枚举上使用开关时都会创建一个额外的合成类。该类包含一个所谓的“切换映射”,它将枚举索引映射到切换表跳转编号。重要的是,合成类是为发生切换的类创建的,不是枚举类。
这是生成的示例:
EnumClass.java
public enum EnumClass { VALUE1, VALUE2, VALUE3 }
EnumUser.java
public class EnumUser {
public String getName(EnumClass value) {
switch (value) {
case VALUE1: return "value 1";
// No VALUE2 case.
case VALUE3: return "value 3";
default: return "other";
}
}
}
综合枚举用户$1.class
class EnumUser$1 {
static final int[] $SwitchMap$EnumClass = new int[EnumClass.values().length];
static {
$SwitchMap$EnumClass[EnumClass.VALUE1.ordinal()] = 1;
$SwitchMap$EnumClass[EnumClass.VALUE3.ordinal()] = 2;
};
}
然后使用此开关映射为lookupswitch 或tableswitch JVM 指令生成索引。它将每个枚举值转换为从 1 到 [开关案例数] 的对应索引。
EnumUser.class
public java.lang.String getName(EnumClass);
Code:
0: getstatic #2; //Field EnumUser$1.$SwitchMap$EnumClass:[I
3: aload_1
4: invokevirtual #3; //Method EnumClass.ordinal:()I
7: iaload
8: lookupswitch{ //2
1: 36;
2: 39;
default: 42 }
36: ldc #4; //String value 1
38: areturn
39: ldc #5; //String value 3
41: areturn
42: ldc #6; //String other
44: areturn
tableswitch 用于如果有三个或更多 switch 案例,因为它执行比lookupswitch 的线性搜索更有效的恒定时间查找。从技术上讲,当 javac 使用 lookupswitch 时,它可以通过合成开关映射省略整个业务。
推测:我手头没有 Eclipse 的编译器可供测试,但我想它不会打扰合成类,而只是使用 lookupswitch。或者,在它“升级”到tableswitch 之前,它可能需要比测试的原始询问器更多的开关案例。