当前位置: 首页 > 面试题库 >

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

谷梁博易
2023-03-14
问题内容

我已经反编译了一个使用新的Java 7 String Switch功能的非常简单的类。

班上:

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”,会生成一组有趣的指令(完整的反汇编代码可在此处获得):

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

“ LOOKUPSWITCH”是在切换大小写稀疏时可以使用的指令,可以替换TABLESWITCH,这是“ switch”语句的默认指令。

因此,问题是,为什么我们会看到“ LOOKUPSWITCH”和“ TABLESWITCH”?

谢谢卢西亚诺


问题答案:

使用字符串进行切换时,找到正确的case语句是一个两步过程。

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

还要注意,指定使用哪个编译器-javac或ECJ(用于Java的Eclipse编译器)很有用。两种编译器可能会不同地生成字节码。



 类似资料:
  • 问题内容: 当我尝试一些类似的代码时,我正在eclipse上开发一个android应用 它给我以下错误 所以我将编译器更改为1.7,这给了我另一个错误 那么,有没有办法让switch(String)在android应用程序中工作?或者我别无选择,只能用 问题答案: 对象声明是Java1.7中引入的新功能。不幸的是,Android需要版本1.6或1.5。这就是为什么您不得不忘记一段时间的这种构造的原

  • 我有一个枚举常量的开关大小写标签。我的枚举和大小写标签示例如下: 整个case标签语句由eclipse用红线标记“case PremisceType. FIRST. toString():”,当我将鼠标悬停在case标签上时,错误显示“case表达式必须是常量表达式”。我的jdk是1.7版,我的eclipse是3.7.2版。有人能告诉我如何解决这个问题吗?

  • 问题内容: 由于某种原因,我收到一条错误消息,但是实际上并没有在读取的任何代码中加下划线。我尝试清洁和重建它,但是没有用。它说它在第49行。 我的代码如下 下面的第49行 问题答案: 你内有两个“奇数”字- U + 200C (零宽不连字)和U + 200B (零宽度的空间)的第一个“e”和“m”个之间。“ l”和“ i”之间的“点击”中出现相同的字符。 只需删除并重新输入这些单词,错误就会消失。

  • 问题内容: 在尝试进入sql查询数组并获得以下javascript错误后,我尝试通过php jquery传递json。 返回sql结果的函数: 以这种方式使用此功能后, 而javascript代码是这样的: 如何纠正此错误以及如何从jquery读取json? 问题答案: 您不需要调用,因为jQuery自动执行该调用,因为如果未指定属性,则jQuery会尝试猜测它并调用正确的函数来解析响应,然后再将

  • 我的pom文件列表 但是,在时,我得到 当我运行时,我看到实际上我使用的是Java6 它可以在哪里定义?我有源(d)my.zshrc多次。

  • 主要内容:到底使用字符数组还是字符串常量C语言中没有特定的字符串类型,我们通常是将字符串放在一个字符数组中,这在《 C语言字符数组和字符串》中已经进行了详细讲解,这里不妨再来演示一下: 运行结果: https://www.xnip.cn https://www.xnip.cn 字符数组归根结底还是一个数组,上节讲到的关于 指针和数组的规则同样也适用于字符数组。更改上面的代码,使用指针的方式来输出字符串: 运行结果: https://ww