Java 7字符串开关反编译:意外指令

Java 7字符串开关反编译:意外指令,java,switch-statement,java-7,decompiling,Java,Switch Statement,Java 7,Decompiling,我已经反编译了一个非常简单的类,它使用了新的Java7字符串开关特性 班级: public class StringSwitch { public static void main(String[] args) { final String color = "red"; switch (color) { case "red": System.out.println("IS RED!");

我已经反编译了一个非常简单的类,它使用了新的Java7字符串开关特性

班级:

public class StringSwitch {

    public static void main(String[] args) {

        final String color = "red";
        switch (color) {
            case "red":
                System.out.println("IS RED!");
                break;
            case "black":
                System.out.println("IS BLACK");
                break;
            case "blue":
                System.out.println("IS BLUE");
                break;
            case "green":
                System.out.println("IS GREEN");
                break;
        }

    }

}
针对该类运行Java 7“javap”,会生成一组有趣的指令(完整的反汇编代码可用):

“LOOKUPSWITCH”是一条在开关大小写稀疏时使用的指令,可以替换表开关,即“switch”语句的默认指令

所以,问题是,为什么我们看到一个“LOOKUPSWITCH”后面跟着一个“TABLESWITCH”

谢谢
在switch中使用字符串查找正确的case语句是一个两步过程

  • 计算开关字符串的hashcode并在case语句中查找“hashcode匹配”,这是通过LOOKUPSWITCH完成的。请注意LOOKUPSWITCH下的大整数,它们是case语句中字符串的哈希代码
  • 现在,两个字符串可以具有相同的哈希代码,尽管可能性不大。因此,实际的字符串比较仍然必须进行。因此,一旦hashcode匹配,开关字符串将与匹配的case语句中的字符串进行比较。LOOKUPSWITCH和TABLESWITCH之间的指令正是这样做的。一旦确认匹配,就可以通过TABLESWITCH访问要为匹配的case语句执行的代码

  • 还请注意,指定您使用的编译器-javac或(eclipsecompilerforjava)是很有用的。两个编译器生成字节码的方式可能不同

    谢谢你的回答。这是有道理的。
    public static void main(java.lang.String[]);
        flags: ACC_PUBLIC, ACC_STATIC
    
        Code:
          stack=2, locals=4, args_size=1
            ...
            12: lookupswitch  { // 4
    
                      112785: 56
    
                     3027034: 84
    
                    93818879: 70
    
                    98619139: 98
                     default: 109
                }
            56: aload_2       
            57: ldc           #2                  // String red
            ...       
           110: tableswitch   { // 0 to 3
    
                           0: 140
    
                           1: 151
    
                           2: 162
    
                           3: 173
                     default: 181
                }
           140: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
           143: ldc           #9                  // String IS RED!
           ...
           181: return