说说Java中你不知道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进阶的文章,感谢关注

说说Java中你不知道switch关键字的更多相关文章
- Java中的50个关键字
form:http://blog.csdn.net/luoweifu/article/details/6776240 Java中的50个关键字 关键字也称为保留字,是指java语言中规定了特定含义的标 ...
- Java中的两个关键字——super、this
Java中的两个关键字——super.this 神话丿小王子的博客主页 一.super super 是java中方的一个关键字,用它可以引用父类中的成员: super可用于访问父类中定义的属性 sup ...
- 【每周一译】愚蠢的指标:Java中使用最多的关键字
此翻译纯属个人爱好,由于水平所限,翻译质量可能较低.网络上可能存在其它翻译版本,原文地址:http://blog.jooq.org/2013/08/26/silly-metrics-the-most- ...
- Java中的标识符和关键字
1.标识符 含义:标识符用于给程序中的类.变量.方法命名的符号. 组成:数字(0-9).字母(a-z)(A-Z).下划线(_).美元符号$. 命名规则:1.数字不能够作为命名符号的开头 2.不能够使用 ...
- 1.3 Java中的标识符和关键字
1.标识符 含义:标识符用于给程序中的类.变量.方法命名的符号. 组成:数字(0-9).字母(a-z)(A-Z).下划线(_).美元符号$. 命名规则:1.数字不能够作为命名符号的开头 2.不能够使用 ...
- java中的标识符、关键字、保留字
Java中关键字(keyword)和保留字(reservedword) Keyword :Java的关键字对java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等. Reserv ...
- Java中this、static关键字的内存图解
Java中的关键字有很多,abstract default goto* null switch boolean do if package nchronzed break dou ...
- java中this和super关键字的使用
这几天看到类在继承时会用到this和super,这里就做了一点总结,与各位共同交流,有错误请各位指正~ this this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针. this ...
- Java中需要知道的关键字
Java中有一些或常用,或不常用,但却不得不知关键字,本篇文章将讨论这些关键字的作用. transient transient关键字可能用的不是那么频繁,但却是一个很重要的关键字,它的作用是在对象序列 ...
随机推荐
- Spark 学习笔记之 aggregateByKey
aggregateByKey: import org.apache.spark.SparkContext import org.apache.spark.rdd.RDD import org.apac ...
- git分支概念与项目中的应用
文档:https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E5%88%86%E6%94%AF%E7%AE%80%E4%BB%8B 分支理解 m ...
- 从0开始学FreeRTOS-1
我们知道,(单核)单片机某一时刻只能干一件事,会造成单片机资源的浪费,而且还有可能响应不够及时,所以,在比较庞大的程序或者是要求实时性比较高的情况下,我们可以移植操作系统.因为这种情况下操作系统比裸机 ...
- Kafka技术原理知识点总结
1.Kafka是由Linkedin公司开发的,使用Scala语言编写的,分布式,多副本,多分区的,发布订阅模式的消息系统,他通常用于日志系统的搭建,2.Kafka和Zookeeper:Kafka通过Z ...
- A-01 最小二乘法
目录 最小二乘法 一.最小二乘法--代数法 二.最小二乘法--矩阵法 三.最小二乘法优缺点 3.1 优点 3.2 缺点 更新.更全的<机器学习>的更新网站,更有python.go.数据结构 ...
- python模块常用用法
1.time模块(※※※※) import time #导入时间模块 print(time.time()) #返回当前时间的时间戳,可用于计算程序运行时间 print(time.localtime() ...
- 【DP合集】合并 union
给出一个 1 ∼ N 的序列 A ( A 1 , A 2 , ..., A N ) .你每次可以将两个相邻的元素合并,合并后的元素权值即为 这两个元素的权值之和.求将 A 变为一个非降序列,最少需要多 ...
- Real Beauty真正的美丽
[1]Beauty is only skin-deep. Physical beauty can only be held fleetingly. Real beauty is much deeper ...
- 数据挖掘:python数据清洗cvs里面带中文字符
数据清洗,使用python数据清洗cvs里面带中文字符,意图是用字典对应中文字符,即key值是中文字符,value值是index,自增即可:利用字典数据结构没有重复key值的特性,把中文字符映射到了数 ...
- Cocos2d-x 学习笔记(11.2) RotateBy RotateTo
1. RotateBy RotateTo 两个旋转方法.RotateBy是在当前角度上旋转设置的角度.RotateTo是直接旋转到设置的角度,方向遵循“就近原则”.两者没有相互继承关系. 1.1 成员 ...