String 的 switch-case 实现原理

前面我们已经知道 String 的 switch-case 实现原理 依据 case 值的稀疏程度,分别由两个指令 - tableswitch 和 lookupswitch 实现,但是这两个指令都支持整型, 如何让 String 类型的值 也支持 String 的 switch-case 实现原理

public class Test {public int switchInt(String  name) {int result;switch (name) {case "Java":result = 100;break;case "Go":result = 200;break;case "Kotlin":result = 300;break;default:result = -1;}return result;}}

javac

public class Test {public Test() {}public int switchInt(String var1) {byte var4 = -1;switch(var1.hashCode()) {case -2041707231:if (var1.equals("Kotlin")) {var4 = 2;}break;case 2312:if (var1.equals("Go")) {var4 = 1;}break;case 2301506:if (var1.equals("Java")) {var4 = 0;}}byte var2;switch(var4) {case 0:var2 = 10;break;case 1:var2 = 20;break;case 2:var2 = 30;break;default:var2 = 40;}return var2;}
}

字节码

C:\>javac Test.javaC:\>javap -c -p Test.classCompiled from "Test.java"
public class com.yxzapp.Test {public com.yxzapp.Test();Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnpublic int switchInt(java.lang.String);Code:0: aload_1                           // 使用iload加载局部变量第1个变量加载栈上1: astore_3							// 将栈顶数据存储到局部变量下标为3的位置2: iconst_m1							// 将 int 类型值 -1 压栈到栈顶3: istore        4                   // 将栈顶元素存储到局部变量第四个位置5: aload_3                           // 加载局部变量第3个变量加载栈上6: invokevirtual #2                  // Method java/lang/String.hashCode:()I9: lookupswitch  { // 3              // 调用 hashcode 方法, 得到一个整型值。												因为哈希值一般比较离散,所以没有选用tablesw											itch,采用lookupswitch 作为实现 	-2041707231: 74 // 对应 Kotlin2312: 59 // 对应 Go2301506: 44 // 对应 Javadefault: 86 }44: aload_345: ldc           #3                  // String Java 47: invokevirtual #4                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z                            // 执行equals 方法50: ifeq          86                  // 判断是否相等53: iconst_0                          // 将 int 类型值1压栈到栈顶54: istore        4                   // 将栈顶int的数据存储到局部变量表的第四个 位置56: goto          86                  // 跳转到86行继续执行59: aload_3 60: ldc           #5                  // String Go62: invokevirtual #4                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z                            65: ifeq          86                  68: iconst_1                          69: istore        4                   71: goto          86                  74: aload_375: ldc           #6                  // String Kotlin77: invokevirtual #4                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z                            // 执行equals 方法80: ifeq          8683: iconst_284: istore        486: iload         488: tableswitch   { // 0 to 20: 1161: 1222: 128default: 134}116: bipush        10118: istore_2119: goto          137122: bipush        20124: istore_2125: goto          137128: bipush        30130: istore_2131: goto          137134: bipush        40136: istore_2137: iload_2138: ireturn
}

可以看到 switch 作用在 String 上最终拆分成两个针对整型 switch 语句,具体流程为:

  1. 做初始化操作,把入参 name 赋值给局部变量表下标为3的变量 , 把初始化局部变量表中位置为4的变量为 -1
    0 1 2 4
    this 入参name “java” -1
  2. 调用 “java” 的 hashCode 方法,得到一个整型值。因为哈希值一般比较离散,所以没有选用tableswitch,采用lookupswitch 作为实现
  3. 如果 hashCode 等于 字符串 “Java” 的 hashCode会跳转到 44 行继续执行,判断是否相等的指令,如果等于 0 则跳转对应字节码处,相等则把 -1 赋值为 0

看到这里可以能会发现, 字符串的 hashCode冲突要怎么样解决

public class Test {public int switchInt(String  name) {int result;switch (name) {case "Aa":result = 10;break;case "BB":result = 20;break;default:result = 40;}return result;}}

javac

public class Test {public Test() {}public int switchInt(String var1) {byte var4 = -1;switch(var1.hashCode()) {case 2112:if (var1.equals("BB")) {var4 = 1;} else if (var1.equals("Aa")) {var4 = 0;}default:byte var2;switch(var4) {case 0:var2 = 10;break;case 1:var2 = 20;break;default:var2 = 40;}return var2;}}
}

字节码

C:\>javac Test.javaC:\>javap -c -p Test.class
Compiled from "Test.java"
public class com.yxzapp.Test {public com.yxzapp.Test();Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnpublic int switchInt(java.lang.String);Code:0: aload_11: astore_32: iconst_m13: istore        45: aload_36: invokevirtual #2                  // Method java/lang/String.hashCode:()I9: lookupswitch  { // 12112: 28default: 55}28: aload_329: ldc           #3                  // String BB31: invokevirtual #4                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z34: ifeq          4337: iconst_138: istore        440: goto          5543: aload_344: ldc           #5                  // String Aa46: invokevirtual #4                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z49: ifeq          5552: iconst_053: istore        455: iload         457: lookupswitch  { // 20: 841: 90default: 96}84: bipush        1086: istore_287: goto          9990: bipush        2092: istore_293: goto          9996: bipush        4098: istore_299: iload_2100: ireturn
}

可以看到34 行在 hashCode 冲突的情况下,编译器的处理不过是多一次调用字符串 equals 判断相等的比较 。与 BB 不相等的情况, 会继续判断是否等于 Aa

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/12038.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】--189.轮转数组

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

Rethinking the Image Fusion(PMGI)

1.摘要 本文提出了一种基于梯度和强度比例维护&#xff08;PMGI&#xff09;的快速统一图像融合网络&#xff0c;可以端到端实现各种图像融合任务&#xff0c;包括红外和可见图像融合、多曝光图像融合、医学图像融合、多焦点图像融合和全色增强。我们将图像融合问题统一为源图…

保姆级系列教程-玩转Fiddler抓包教程(1)-HTTP和HTTPS基础知识

1.简介 有的小伙伴或者童鞋们可能会好奇地问&#xff0c;不是讲解和分享抓包工具了怎么这里开始讲解HTTP和HTTPS协议了。这是因为你对HTTP协议越了解&#xff0c;你就能越掌握Fiddler的使用方法&#xff0c;反过来你越使用Fiddler&#xff0c;就越能帮助你了解HTTP协议。 Fid…

Java | 继承、多态、抽象类与接口

目录 一、类的继承 二、Object类 2.1 getClass()方法 2.2 toString()方法 2.3 equals()方法 三 、对象类型的转换 3.1 向上转换 3.2 向下转型 四、使用instanceof关键字判断对象类型 五、方法的重载 六、final关键字 6.1 final变量 6.2 final方法 6.3 final类 七…

安装x265

一、编译libx265源码 libx265是用CMAKE编译的&#xff0c;故先下cmake&#xff0c;我是centos系统&#xff0c;命令&#xff1a; yum install cmake -y进入目录./x265_1.9/build/linux/下&#xff0c;执行脚本&#xff1a; sh make-Makefiles.bash选择好之后&#xff0c;输入…

【多模态】19、RegionCLIP | 基于 Region 来实现视觉语言模型预训练

文章目录 一、背景二、方法2.1 Region-based Language-Image Pretraining2.2 目标检测的迁移学习 三、效果3.1 数据集3.2 实现细节3.3 结果 论文&#xff1a; RegionCLIP: Region-based Language-Image Pretraining 代码&#xff1a;https://github.com/microsoft/RegionCLIP …

了解Unity编辑器之组件篇Playables和Rendering(十)

Playables 一、Playable Director&#xff1a;是一种用于控制和管理剧情、动画和音频的工具。它作为一个中央控制器&#xff0c;可以管理播放动画剧情、视频剧情和音频剧情&#xff0c;以及它们之间的时间、顺序和交互。 Playable Director组件具有以下作用&#xff1a; 剧情控…

Vue中使用echarts

1 安装 npm install -g cnpm --registryhttps://registry.npm.taobao.org cnpm install echarts -S 2 main.js引入 3 引入成功

perl 拼接字符串

在Perl中&#xff0c;你可以使用不同的方法来拼接字符串。以下是一些常用的方法&#xff1a; 使用.运算符拼接字符串&#xff1a; my $str1 "Hello, "; my $str2 "World!"; my $result $str1 . $str2; print $result; # 输出&#xff1a;Hello, Worl…

探索Java API学习路线:从基础到高级的全面指南

文章目录 第一阶段&#xff1a;入门基础1. 环境准备2. 学习Java基础 第二阶段&#xff1a;熟悉常用的Java API1. Java标准库2. Java API文档 第三阶段&#xff1a;深入学习特定领域的Java API1. Java GUI API2. Java数据库连接&#xff08;JDBC&#xff09;API3. Java多线程API…

【蓝图】p44简单解密机关

p44简单解密机关 p44简单解密机关文字提示开门文字提示开灯For Each Loop和For Each Loop With Break区别For Each LoopFor Each Loop With Break小操作&#xff1a;改变走线Execute Console Command(执行控制台命令) p44简单解密机关 文字提示开门 创建Actor蓝图类&#xff…

Python及PyCharm安装教程

1.Python安装教程 python官网下载windows64位python installer&#xff1b; 这里选择windows installer(64-bit) 打开下载完成的installer文件 记得勾选上Add python.exe to PATH&#xff0c;再点击Install Now&#xff1b; &#xff08;如果想要更改安装位置&#xff0c;需要…

【使用时空RBF-NN进行非线性系统识别】实现了 RBF、分数 RBF 和时空 RBF 神经网络,用于非线性系统识别研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 2.1 算例1 2.2 算例2 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码实现 &#x1f4a5;1 概述 本文用于非线性系统识别任务的径向基函数神经网络&#xff08;RBF-NN&#xff09;的三种变体。特别是&#xff0c;我实现…

MYSQL DCL语句

MySQL DCL语句 简介 DQL是用于查询和检索数据库数据的重要工具。它具有丰富的功能和灵活性&#xff0c;可以根据不同的查询需求进行条件过滤、排序、聚合计算等操作。通过合理使用DQL&#xff0c;可以从数据库中提取有用的数据以进行数据分析和决策支持。 DCL语句的分类 DC…

Swoole协程系统HTTP服务

先启动宝塔 /etc/init.d/bt start 源码参考 https://github.com/zhangyue0503/swoole/tree/main/4.Swoole%E5%8D%8F%E7%A8%8B 对于异步来说&#xff0c;我们需要监听事件&#xff0c;并且监听的进程是并发的&#xff0c;所以会有一个问题&#xff0c;那就是无法保证前后顺…

33.Oracle的Sid重复问题

oracle安装sid重复问题 Oracle卸载后再次安装&#xff0c;设置的SID相同出现“指定的SID在本机上已经存在。请指定一个不同的SID。” 1. SID简介 SID也就是安全标识符&#xff08;Security Identifiers&#xff09;&#xff0c;是标识用户、组和计算机帐户的唯一的号码。在第…

redis到底几个线程?

通常我们说redis是单线程指的是从接收客户端请求->解析请求->读写->响应客户端这整个过程是由一个线程来完成的。这并不意味着redis在任何场景、任何版本下都只有一个线程 为何用单线程处理数据读写&#xff1f; 内存数据储存已经很快了 redis相比于mysql等数据库是…

宋浩高等数学笔记(八)向量代数与空间解析几何

本章知识点并不难理解&#xff0c;但是公式与名词属于非常多&#xff0c;记忆时需重点对待。

lc154.寻找旋转排序数组中的最小值

最小元素的位置以旋转次数为索引的位置&#xff0c;但是没有告诉旋转次数&#xff0c;换一种思路 当遇到arr[index] > arr[index1]时&#xff0c;index1为最小元素的位置。首位位置独立比较。但是这种方法还是遍历数组 观察两组数的中间值与首尾的值&#xff0c;又由于数组…

vue动态引入静态资源

vue动态引入静态资源 静态资源位置&#xff08;../../assets/piecture/page404.jpg&#xff09;或者&#xff08;/assets/piecture/page404.jpg&#xff09; 错误引入方式 错误引入方式&#xff08;一&#xff09; <template><div><img :src"../../asset…