switch(String)语法糖解析

Java1.5之前,switch语法结构仅支持int, byte, short, char这几个基本类型(及对应的包装类型)。

1.5后提供了enum枚举结构。

Java7提供了switch(String)结构。

问题一

经常听到Java7中提供的switch(String)是Java语言的一个语法糖,实际JVM并不支持这个语法结构,但这个语法糖具体是怎么实现的,一直没有看过,今天比较有空,我来研究一下。

首先写一段switch结构的代码。

public static void main(String[] args) {final String str = "F";switch (str) {case "A" :System.out.println("A");break;case "B" :System.out.println("B");break;default:System.out.println("F");}}

查看idea反编译后的源码。

public static void main(String[] args) {String str = "F";String var2 = "F";byte var3 = -1;switch(var2.hashCode()) {case 65:if (var2.equals("A")) {var3 = 0;}break;case 66:if (var2.equals("B")) {var3 = 1;}}switch(var3) {case 0:System.out.println("A");break;case 1:System.out.println("B");break;default:System.out.println("F");}}

可以看到,switch结构中变为了String.hashcode()方法,利用其返回的int值进行判断,所以说编译后还是使用了switch(int)结构来实现的。大家都知道String的hashcode方法是有哈希冲突的风险的,所以在每个case条件中增加了equals作为补充判断,避免哈希冲突错误。

问题二

上面说增加了equals,这样能避免哈希冲突导致问题,但哈希冲突时,比如case(“A”) ,case(“B”),加入A和B会计算出相同的hash值,那岂不是两个case的条件一样,那这样应该连编译都通不过呀。所以我找了一个哈希冲突的例子来试一下(找了半天没找到,看到一篇博客里找到了)

public static void main(String[] args) {final String str = "test";switch (str) {case "AaAa":System.out.println("a");break;case "BBBB":System.out.println("b");break;case "AaBB":System.out.println("c");break;default:System.out.println("c");break;}}

反编译源码

public static void main(String[] args) {String str = "test";String var2 = "test";byte var3 = -1;switch(var2.hashCode()) {case 2031744:if (var2.equals("AaBB")) {var3 = 2;} else if (var2.equals("BBBB")) {var3 = 1;} else if (var2.equals("AaAa")) {var3 = 0;}default:switch(var3) {case 0:System.out.println("a");break;case 1:System.out.println("b");break;case 2:System.out.println("c");break;default:System.out.println("c");}}}

果然反编译后的结构发生了变化,源代码里三个相同hash值的case,编译后只有一个case,里面使用了if else的结构来做判断,这样就万无一失了,确实解决了哈希冲突的场景。

问题三

看反编译后的代码,还会有一个问题,为什么一个switch编译后会拆分为两个switch结构,为什么要新增一个switch(byte)结构呢,这样貌似不是必要的,仅仅通过上面的switch和if else结构就足以应付各种场景了。增加一个结构反而会影响性能。那么到底是什么原因导致增加一个switch(byte)结构呢。这个答案是看一篇博客找到的。

看下面这种场景

public static void main(String[] args) {final String str = "test";switch (str) {case "AaAa":System.out.println("a");case "BBBB":System.out.println("b");break;case "AaBB":System.out.println("c");break;default:System.out.println("c");break;}}
public static void main(String[] args) {String str = "test";String var2 = "test";byte var3 = -1;switch(var2.hashCode()) {case 2031744:if (var2.equals("AaBB")) {var3 = 2;} else if (var2.equals("BBBB")) {var3 = 1;} else if (var2.equals("AaAa")) {var3 = 0;}default:switch(var3) {case 0:System.out.println("a");case 1:System.out.println("b");break;case 2:System.out.println("c");break;default:System.out.println("c");}}}

看到这里应该就明白了,是因为switch的特殊语法结构,自上而下地处理每个条件,在不加break的时候,会继续进行下一个条件的判断。在上面那种case + if else 时就处理不了这种情况,所以第一个switch结构只是为了解决哈希冲突的问题,唯一定位一个case,下面的switch(byte)才是执行。而且这样的写法会比较清晰。

switch(String)语法糖解析相关推荐

  1. Flutter 里的语法糖解析,知其所然方能潇洒舞剑

    本篇主要针对 Flutter 里 Dart 的一些语法糖实现进行解析,让你明显简单声明的关键字背后,Dart 究竟做了什么? 如下图所示,起因是昨天在群里看到一个很基础的问题,问: "这段代 ...

  2. Flutter 里的语法糖解析,知其所然方能潇洒舞剑 | 开发者说·DTalk

    本文原作者: 恋猫de小郭,原文发布于: GSYTech 本篇主要针对 Flutter 里 Dart 的一些语法糖实现进行解析,让您明白简单声明的关键字背后,Dart 究竟做了什么? 如下图所示,起因 ...

  3. Flutter 里的语法糖解析,知其所然方能潇洒舞剑,安卓开发面试题及答案

    介绍完 late 接下介绍下 typedef, typedef 在 Dart 2.13 开始可以用于**「新的类型别名功能」**,比如: // Type alias for functions (ex ...

  4. Flutter 里的语法糖解析,知其所然方能潇洒舞剑,为什么阿里的程序员成长如此之快

    ================================================================ 首先如下图所示,我们写一段简单的代码,通过 late 声明了一个 pl ...

  5. Flutter 里的语法糖解析,知其所然方能潇洒舞剑,10天用Flutter撸了个高仿携程App

    如下图所示,「起因是昨天在群里看到一个很基础的问题」,问: "这段代码为什么不能对 user 进行判空?" . 其实这个问题很简单: 1.在 Dart 的 **「Sound Nul ...

  6. Java中switch参数传null会引起异常——Java 语法糖

    问题 switch 参数不能是null,swicth(null)会报java.lang.NullPointerException异常 查找原因 为什么会这样呢,查找一下原因: 找到编译后的class文 ...

  7. 怎么new 一个String数组,以数组的形式输出, 以及语法糖

    方法一: Integer length = 5;//自定义数组长度 String[] strArray = new String[length ]; 方法二: String[] strArray = ...

  8. 阿里云面试:什么是语法糖?Java中有哪些语法糖?

    点击上方"芋道源码",选择"设为星标" 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | ...

  9. Android学习-Kotlin语言入门-变量、函数、语法糖、when、for-in、主构造函数、单例类、函数式API、集合遍历、隐式Intent、Activity生命周期、四种启动模式、标准函数

    探究java语言的运行机制 变量.函数.语法糖 when条件语句 for循环 主构造函数.次构造函数 数据类和单例类 集合的创建与遍历 集合的函数式API 创建菜单 隐式使用Intent Activi ...

最新文章

  1. 算法题解:对于输入数字串,给出另一种数字排列,使得字典序增加尽可能小...
  2. 《LeetCode力扣练习》第11题 C语言版 (做出来就行,别问我效率。。。。)
  3. html字体效果标签,纯CSS模拟fieldset标签效果把文字写在边框上
  4. java如何使显示字符下标_Java如何在 Word 中设置上、下标
  5. SLF4j、log4j管理系统日志(Maven)
  6. html传递json中文乱码,解决后台传数据到前台中文乱码问题,使用@ResponseBody返回json 中文乱码...
  7. ubuntu 开机自动挂在windows下的分区
  8. 发现个好玩的,去页面敲键盘,页面键变色
  9. 【昇润蓝牙】蓝牙4.0BLE模组(型号CC2541) 两个蓝牙之间互相通信的使用日志
  10. JZOJ5442【NOIP2017提高A组冲刺11.1】荒诞 三进制状压+欧拉序
  11. 06-----the inferior stopped because it triggered an exception
  12. 极域电子教室学生机房管理助手(好好上课)教程
  13. 15 个有趣的 JS 和 CSS 库
  14. 基于React Native和Ethers.js的电子钱包(二):路由和导航
  15. 速卖通商品详情API接口(商品详情页面数据接口)
  16. table的样式设置
  17. linux获取时间,精确到微秒usec
  18. 【web项目】前端生日礼物--clock篇
  19. 谷粒学院讲师模块学习
  20. 程序员离职原因的最佳回答_C#关于程序员妹子,那些你遇到的女程序员

热门文章

  1. 学习java后端第二步-eclipse配置tomcat并成功跑起来
  2. ORA-19566 exceeded limit of 0 corrupt blocks数据坏块处理
  3. php addslashes 数组,PHP函数漏洞审计之addslashes函数-
  4. liquibase介绍,liquibase这一篇就够了
  5. tomcat启动出现闪退_tomcat启动闪退怎么办
  6. 基于javaweb的电影院会员管理系统(java+springboot+vue+element-ui+mysql)
  7. 栈的顺序存储结构(顺序栈)
  8. 怎么将闲鱼当副业?闲鱼副业怎么运营?闲鱼如何弄副业?
  9. Git 注册、安装、配置、命令
  10. stm32+lwip 的先启动后插网线的处理方法