这篇文章主要介绍了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可以被编译为两种指令
并且文档中还有一段描述:
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 关键字super详解及用法,包括了java 关键字super详解及用法的使用技巧和注意事项,需要的朋友参考一下 java 关键字super详解 一、super关键字 在JAVA类中使用super来引用父类的成分,用this来引用当前对象,如果一个类从另外一个类继承,我们new这个子类的实例对象的时候,这个子类对象里面会有一个父类对象。怎么去引用里面的父类对象呢?使用
本文向大家介绍Java静态static关键字原理详解,包括了Java静态static关键字原理详解的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了Java静态static关键字原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 static关键字既可以修饰成员变量,也可以修改成员方法,修饰的成员变量和成员方法可以直接通过类名调用,
本文向大家介绍PHP var关键字相关原理及使用实例解析,包括了PHP var关键字相关原理及使用实例解析的使用技巧和注意事项,需要的朋友参考一下 见很多朋友说在php中定义变量用不用var都没关系,其实不然。 看看例子,如果我这样使用var: 那var什么时候才能用,请看: 如果把var换成public,一样可以的。 但是这个时候你在类中去掉var,什么访问修饰符都没有,那会提示语法错误的。 其
本文向大家介绍spring jpa ManyToMany原理及用法详解,包括了spring jpa ManyToMany原理及用法详解的使用技巧和注意事项,需要的朋友参考一下 1.java和jpa 中所有的关系都是单向的。这个关系数据库不同,关系数据库,通过外键定义并查询,使得反向查询总是存在的。 2.JPA还定义了一个OneToMany关系,它与ManyToMany关系类似,但反向关系(如果已定
本文向大家介绍Python字符串函数strip()原理及用法详解,包括了Python字符串函数strip()原理及用法详解的使用技巧和注意事项,需要的朋友参考一下 strip:用于移除字符串头尾指定的字符(默认为空格)或字符序列。注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。 语法:str.strip([chars]) str = "*****this is **string**
本文向大家介绍Delphi常用关键字用法详解,包括了Delphi常用关键字用法详解的使用技巧和注意事项,需要的朋友参考一下 本文详细介绍了Delphi中常用的各个关键字名称及用法,供大家在编程过程中借鉴参考之用。详情如下: absolute: abstract: and: array: as: asm: assembler: automated: begin: case: cdecl: class