说一说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 ...
随机推荐
- 【设计模式】Composite
目录 前言 安卓View的实现 View Beyond setContentView setContentView做了什么事情? 如何将xml文件变成对象的? 小结 View的绘制流程 三个流程 三个 ...
- deepin可视化程序打不开问题排查方法
anyconnect是一个VPN软件,在deepin系统下安装完成之后,并不能够直接使用,点击启动图标之后没有反应. 要想分析问题,必须从命令行入手,错误会打印在控制台. 如何根据一个图标来找到一个程 ...
- opencv::KMeans图像分割
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...
- 谷歌移动UI框架Flutter入门
引言 作为Android开发人员,很有必要学习一下Flutter,那么Flutter是什么呢?它到底有什么作用呢?我们一一来揭晓. Flutter是谷歌的移动UI框架,可以快速在iOS和Android ...
- emoji表情多终端适配解决方案
emoji表情多终端适配解决方案 emoji,也叫 颜表情 是日本在无线通信中所使用的视觉情感符号,由栗田穰崇(Shigetaka Kurita)创作,并在日本网络及手机用户中流行.自苹果公司发布的i ...
- 基于Anaconda编译caffe+pycaffe+matcaffe in Ubuntu[不用sudo权限]
目录 caffe 编译 环境 github下载caffe源码 依赖 修改源码的编译配置 报错 测试使用 pycaffe caffe matcaffe caffe 编译 环境 Ubuntu16.04 C ...
- vue如何解析xml文件 x2js
好久没来写东西了,主要是一直在加班,哼哼,不开心 项目中会用到将xml文件解析成json文件在页面中显示出来,以前jq的时候用到的方法行不通了,故在这边介绍一种我觉得还不错的插件 1. npm安装 n ...
- 02微信小程序-轮播的宽度100%显示和轮播的基础配置
1==>如何让轮播的宽度100%显示? 你先给swiper 外面添加一个大盒子,给大盒子一个类 . <view class='lunbobox'> 然后wxss 里面设置 image ...
- 201871010132--张潇潇--《面向对象程序设计(java)》第十二周学习总结
博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...
- HDFS 分布式文件系统
博客出处W3c:https://www.w3cschool.cn/hadoop/xvmi1hd6.html 简介 Hadoop Distributed File System,分布式文件系统 架构 B ...