switch
做为Java内置关键字,却在项目中真正使用的比较少。关于switch
,仍是有那么一些奥秘的。html
确实,项目中使用switch
比较少的一个主要缘由就在于它的做用能被if-else
代替,何况switch
对类型的限制,也阻碍了switch
的进一步使用。java
先看看switch
的语法:微信
switch(exp){ case exp1: break; case exp2: break; default: break; }
其中exp
的类型限制为:byte ,short , int , char,
及其包装类,以及枚举和String
(JDK1.7)oracle
若是说,switch
的功能和if-else
的如出一辙,那么它存在的意义在哪里?jvm
答案是: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
结果以下:ui
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,我猜应该是基于性能和实现的复杂度的考量吧。
咱们明白了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进阶的文章,感谢关注