• Java中String的switch-case字节码与等价实现代码


    Java中String的switch-case字节码与等价实现代码

    switch-case 语句在 case 比较稀疏的情况下,编辑器会使用 lookupswitch 指令来实现,反之,编辑器会使用 tableswitch 来实现。
    对于 String 的 switch-case 中会将 case 后面的string转化成哈希值,而哈希值一般是比较稀疏的,所以选择 lookupswitch 来作为switch-case来实现。

    拿下面例子说明:

    public int test(String name) {
        switch (name) {
            case "Java":
                return 100;
            case "Kotlin":
                return 200;
            default:
                return -1;
        }
    }
    

    上面代码的字节码如下:

     0 : aload_1
     1 : astore_2             // 将name赋值给局部变量表下标为2的变量
     2 : icount_m1            // -1
     3 : istore_3             // 初始化局部变量表中位置为3的变量为-1
    
     4 : aload_2
     5 : invokevirtual   #2   // Method java/lang/String.hashCode:()
     8 : lookupswitch {
        -2041707231: 50       // 对应 "Kotlin".hashCode()
            2301506: 36       // 对应 "Java".hashCode()
            default: 61
        }
    
    36 : aload_2
    37 : ldc             #3    // String Java 从常量池压栈到栈顶
    39 : invokevirtual   #4    // Method java/lang/String.equals:(Ljava/lang/Object;)z
    42 : ifeq            61    // 如果等于 0 (false)则跳到 对应字节码行处
    45 : iconst_0
    46 : istore_3
    47 : goto            61
    
    50 : aload_2
    51 : ldc             #5    // String Kotlin 从常量池压栈到栈顶·
    53 : invokevirtual   #4    // Method java/lang/String.equals:(Ljava/lang/Object;)z
    56 : ifeq            61
    59 : iconst_1
    60 : istore_3
    
    61 : iload_3
    62 : lookupswitch {
                  0: 88
                  1: 91
            default: 95
        }
    
    88 : bipush          100   // 将范围在-128~127 的整形值压栈到栈顶
    90 : ireturn
    
    91 : sipush          200   // 将范围在-32768~32767 的整形值压栈到栈顶
    94 : ireturn
    
    95 : iconst_m1       -1
    96 : ireturn
    

    结合字节码我们可以推出其的等价实现代码:

    public int test_translate(String name) {
        String tmpName = name;
        int matchIndex = -1;
        switch (tmpName.hashCode()) {
            case -2041707231:
                if ( tmpName.equals("Kotlin")) 
                    matchIndex = 1;
                break;
            case 2301506:
                if ( tmpName.equals("Java")) 
                    matchIndex = 0;
                break;
            default:
                break;
        }
        switch (matchIndex) {
            case 0:
                return 100;
            case 1:
                return 200;
            default:
                return -1;
        }
    }
    

    对字符串去哈希值时会面临冲突问题,比如 Aa 和 BB 的hashCode 都是2112。对代码稍微修改即可,如下:

    public int test_translate(String name) {
        String tmpName = name;
        int matchIndex = -1;
        switch (tmpName.hashCode()) {
            case 2112:
                if ( tmpName.equals("BB"))
                    matchIndex = 1;
                else if ( tmpName.equals("Aa"))
                    matchIndex = 0;
                break;
            default:
                break;
        }
        switch (matchIndex) {
            case 0:
                return 100;
            case 1:
                return 200;
            default:
                return -1;
        }
    }
    
  • 相关阅读:
    mysql函数
    maven 配置自动本地/线上不同配置自动打包
    maven clean后 编译报错
    htmlunit填坑
    java正则表达式移除网页中注释代码
    spark 计算结果写入mysql 案例及常见问题解决
    pychrome激活
    hadoop集群常见问题解决
    hadoop+spark集群搭建
    C++:构造函数2——拷贝构造函数
  • 原文地址:https://www.cnblogs.com/jiaohuadehulike/p/14294952.html
Copyright © 2020-2023  润新知