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_01: lookupswitch{ // 21: 282: 39default: 50} ...这里面省略一些代码 。
可以发现,switch
是通过lookupswitch
指令实现 。那么lookupswitch
指令是干嘛的呢?
在Java se8文档中的描述可以大概知道:
switch
可以被编译为两种指令
lookupswitch
:当switch
的case
比较稀疏的时候,使用该指令对int
值的case
进行一一比较 , 直至找到对应的case
(这里的查找,可以优化为二分查找)tableswitch
:当switch
的case
比较密集的时候,使用case
的值作为switch
的下标,可以在时间复杂度为O(1)的情况下找到对应的case
(可以类比HashMap
)
现在,我们应该能够明白,为什么The Java Virtual Machine's tableswitch and lookupswitch instructions operate only on int data. Because operations on byte, char, or short values are internally promoted to int, a switch whose expression evaluates to one of those types is compiled as though it evaluated to type int. If the chooseNear method had been written using type short, the same Java Virtual Machine instructions would have been generated as when using type int. Other numeric types must be narrowed to type int for use in a switch.
大概翻译如下:Java
虚拟机的tableswitch
和lookupswitch
指令仅对int
数据进行操作 。因为对byte
、char
或short
值的操作在内部被提升为int
, 所以其表达式计算为这些类型之一的switch
被编译为好像它计算为int
类型 。如果使用short
类型编写了chooseNear
方法,则将生成与使用int
类型时相同的Java
虚拟机指令 。其他数字类型要在switch
中使用必须转为int
类型 。
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;}}
推荐阅读
- 二 Java多线程-线程关键字
- switch上古卷轴5mod怎么用(switch上古卷轴5mod视频)
- 说说 Redis 事务
- Switch什么时候出Pro_SwitchPro什么时候上市
- 为了讲明白继承和super、this关键字,群主发了20块钱群红包
- Vue中使用Switch开关用来控制商品的上架与下架情况、同时根据数据库商品的状态反应到前台、前台修改商品状态保存到数据库
- switch为什么这么火_switch火爆原因
- 微信朋友圈怎么转发图片说说(微信想转发朋友圈的说说和图片)
- 说说芦荟胶 我一共用过4款芦荟胶,分别是自然乐园芦荟胶、丹姿芦荟胶、韩束芦荟胶和百雀羚三生花芦荟胶。
- 说说传说中的KFC御用豆浆,为什么这么好喝