说一说switch关键字的奥秘
Switch语法
switch作为Java内置关键字,却在项目中真正使用的比较少。关于switch,还是有那么一些奥秘的。

要什么switch,我有if-else
确实,项目中使用switch比较少的一个主要原因就在于它的作用能被if-else代替,况且switch对类型的限制,也阻碍了switch的进一步使用。
先看看switch的语法:
switch(exp){
case exp1:
break;
case exp2:
break;
default:
break;
}
其中exp的类型限制为:byte ,short , int , char,及其包装类,以及枚举和String(JDK1.7)
为什么要有这些限制?
如果说,switch的功能和if-else的一模一样,那么它存在的意义在哪里?
答案是:switch和if-else在设计的时候,是有一定的性能差别的。
看代码:
public class Test {
public static void switchTest(int a) {
switch (a) {
case 1:
System.out.println("1");
break;
case 2:
System.out.println("2");
break;
default:
System.out.println("3");
break;
}
}
}
javap -c Test.class
结果如下:
public static void switchTest(int);
Code:
0: iload_0
1: lookupswitch { // 2
1: 28
2: 39
default: 50
}
...
这里面省略一些代码。
可以发现,switch是通过lookupswitch指令实现。那么lookupswitch指令是干嘛的呢?
在Java se8文档中的描述可以大概知道:
switch可以被编译为两种指令
lookupswitch:当switch的case比较稀疏的时候,使用该指令对int值的case进行一一比较,直至找到对应的case(这里的查找,可以优化为二分查找)tableswitch:当switch的case比较密集的时候,使用case的值作为switch的下标,可以在时间复杂度为O(1)的情况下找到对应的case(可以类比HashMap)
并且文档中还有一段描述:
Java虚拟机的
tableswitch和lookupswitch指令仅对int数据有效。因为对byte,char或或short值的操作在内部被提升为int,所以对其switch表达式求值为其中一个类型进行编译,就好像它被计算为要键入一样int。如果chooseNear方法是使用type编写的,则使用类型时short将生成相同的Java虚拟机指令int。其他数字类型必须缩小到类型int以便在a中使用switch。
现在,我们应该能够明白,为什么switch关键字会有类型限制了,因为 switch所被翻译的关键字是被限制为int类型的,至于为什么是int,我猜应该是基于性能和实现的复杂度的考量吧。
int之外的类型
我们明白了byte,shor,char,int能被作为switch类型后,再看看枚举和String
public static void switchTest(String a) {
switch (a) {
case "1":
System.out.println("1");
break;
case "2":
System.out.println("2");
break;
default:
System.out.println("3");
break;
}
}
编译生成Test.class。拖入IDEA进行反编译得到如下代码:
public static void switchTest(String a) {
byte var2 = -1;
switch(a.hashCode()) {
case 49:
if (a.equals("1")) {
var2 = 0;
}
break;
case 50:
if (a.equals("2")) {
var2 = 1;
}
}
switch(var2) {
case 0:
System.out.println("1");
break;
case 1:
System.out.println("2");
break;
default:
System.out.println("3");
}
}
可以看见,JDK7 所支持的String类型是通过获取String的hashCode来进行选择的,也就是本质上还是int.为什么String可以这样干?这取决于String是一个不变类。
为了防止hash碰撞,代码更加保险的进行了
equals判断。
再来看看Enum
public static void switchTest(Fruit a) {
switch (a) {
case Orange:
System.out.println("Orange");
break;
case Apple:
System.out.println("Apple");
break;
default:
System.out.println("Banana");
break;
}
}
编译生成Test.class。拖入IDEA进行反编译得到如下代码:
public static void switchTest(Fruit a) {
switch(1.$SwitchMap$com$dengchengchao$Fruit[a.ordinal()]) {
case 1:
System.out.println("Orange");
break;
case 2:
System.out.println("Apple");
break;
default:
System.out.println("Banana");
}
}
可以看到,枚举支持switch更加简单,直接通过枚举的顺序即可作为相关case
总之:
switch的设计按道理来说,是比if-else要快的,但是在99.99%的情况下,他们性能差不多,除非case分支量巨大,但是在case分支过多的情况下,一般应该考虑使用多态重构了。switch虽然支持byte,int,short,char,enum,String但是本质上都是int,其他的只是编译器帮你进行了语法糖优化而已。
尊重劳动成果,转载注明出处
如果觉得写得不错,欢迎关注微信公众号:逸游Java ,每天不定时发布一些有关Java进阶的文章,感谢关注

说一说switch关键字的奥秘的更多相关文章
- 说说Java中你不知道switch关键字
Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的 ...
- 说说switch关键字
Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的 ...
- c#关键字详解
c#关键字 关键字是对编译器有特殊意义的预定义的保留标识符.它们不能在程序中用作普通标识符,除非在它们前面加上@前缀. 第一部分 一.访问关键字:base,this base:访问基类的成员. 用 ...
- 你好,C++(20).4.2.2 表达并列条件选择的switch语句:如果……如果……如果……
4.2.2 表达并列条件选择的switch语句:如果……如果……如果…… 在现实世界中,还有这样一类特殊的条件选择: 如果明天是晴天,我就穿T恤: 如果明天是阴天,我就穿衬衣: 如果明天是雨天,我就 ...
- Powershell Switch 条件
Powershell Switch 条件 6 21 1月, 2012 在 Powershell tagged Powershell教程/ 分支/ 字符串/ 数字/ 条件by Mooser Lee 本 ...
- 选择结构switch
1.选择结构switch switch 条件语句也是一种很常用的选择语句,它和if条件语句不同,它只能针对某个表达式的值作出判断,从而决定程序执行哪一段代码.例如,在程序中使用数字1~7来表示星期一到 ...
- Switch语句的参数是什么类型的?
在Java5以前,switch(expr)中,exper只能是byte,short,char,int类型. 从Java5开始,java中引入了枚举类型,即enum类型. 从Java7开始,exper还 ...
- 带标签的循环语句、switch
今天继续更新,控制流程的剩余部分内容,带标签的循环语句中的continue/break 的使用方法,以及switch关键字的使用方法.例1:带标签的continue/break.package com ...
- GoLang学习控制语句之switch
基本结构 相比较 C 和 Java 等其它语言而言,Go 语言中的 switch 结构使用上更加灵活.它接受任意形式的表达式,例如: switch var1 { case val1: ... case ...
随机推荐
- jQuery 的58种事件方法你都用过了吗
jQuery 事件方法 事件方法触发或将函数附加到所选元素的事件处理程序. 下表列出了用于处理事件的所有jQuery方法. 方法 描述 bind() 在3.0版中已弃用. 请改用on()方法.将事件处 ...
- Arduino+esp8266-01+舵机 制作基于局域网的遥控门禁
这个最终的效果呢,就是可以通过手机连接上esp8266创建的wifi,然后连接其创建的服务器,发送特定指令就可实现遥控开门 (做工比较粗糙还请不要见笑...) 一.原理 其实这个一看就会明白,非常简单 ...
- maven 学习---Maven添加远程仓库
默认情况下,Maven从Maven中央仓库下载所有依赖关系.但是,有些库丢失在中央存储库,只有在Java.net或JBoss的储存库远程仓库中能找到. 1. Java.net资源库 添加Java.ne ...
- Java并行程序基础。
并发,就是用多个执行器(线程)来完成一个任务(大任务)来处理业务(提高效率)的方法.而在这个过程中,会涉及到一些问题,所以学的就是解决这些问题的方法. 线程的基本操作: 1.创建线程:只需要new一个 ...
- 单点登录,系统B如何辨别用户已登录系统A
首先系统A去访问受限资源,跳转到sso认证中心https://login.sso.com/login?redirectURL=https://www.a.com/center,用户登录成功之后,sso ...
- 操作Excel模块openpyxl
安装 pip install openpyxl 想要在文件中插入图片文件,需要安装pillow font(字体类):字号.字体颜色.下划线等 fill(填充类):颜色等 border(边框类):设置单 ...
- Rust中的错误处理
Result & Panic 这次讲得详细,从错误的来历及简写过程, 都写明白了, 先浅,再深,先深,再浅, 反复之, 学习王道~ use std::fs::File; //use std:: ...
- JS高阶---执行上下文栈
大纲: 主体: 注意:*******函数调用时才会产生上下文栈,声明时不会产生********** 顺序: 概念图: 执行上下文栈的顺序---→后进先出 其他概念图: 当前执行的上下文总是在顶部 全局 ...
- 第24课经典问题(中)-----关于const对象的疑问
关于const对象的疑问const关键字能否修饰类的对象?如果可以,有什么特性?const关键字能够修饰对象const修饰的对象为只读对象只读对象的成员变量不允许被改变.(对象是只读的,成员变量不允许 ...
- Hive学习之修改表、分区、列
Hive学习之修改表.分区.列 https://blog.csdn.net/skywalker_only/article/details/30224309 https://www.cnblogs.co ...