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的一模一样,那么它存在的意义在哪里?

答案是:switchif-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:当switchcase比较稀疏的时候,使用该指令对int值的case进行一一比较,直至找到对应的case(这里的查找,可以优化为二分查找)
  • tableswitch:当switchcase比较密集的时候,使用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 虚拟机的 tableswitchlookupswitch 指令仅对 int 数据进行操作。 因为对 bytecharshort 值的操作在内部被提升为 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类型是通过获取StringhashCode来进行选择的,也就是本质上还是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更加简单,直接通过枚举的顺序(order属性)即可作为相关case

总结

总之:

  • switch的设计按道理来说,是比if-else要快的,但是在99.99%的情况下,他们性能差不多,除非case分支量巨大,但是在case分支过多的情况下,一般应该考虑使用多态重构了。
  • switch虽然支持byte,int,short,char,enum,String但是本质上都是int,其他的只是编译器帮你进行了语法糖优化而已。

尊重劳动成果,转载注明出处

~~

微信搜索公众号:StackTrace,关注我们,不断学习,不断提升

说说switch关键字的更多相关文章

  1. 说说Java中你不知道switch关键字

    Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的 ...

  2. 说一说switch关键字的奥秘

    Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的 ...

  3. c#关键字详解

    c#关键字   关键字是对编译器有特殊意义的预定义的保留标识符.它们不能在程序中用作普通标识符,除非在它们前面加上@前缀. 第一部分 一.访问关键字:base,this base:访问基类的成员. 用 ...

  4. 你好,C++(20).4.2.2 表达并列条件选择的switch语句:如果……如果……如果……

    4.2.2  表达并列条件选择的switch语句:如果……如果……如果…… 在现实世界中,还有这样一类特殊的条件选择: 如果明天是晴天,我就穿T恤: 如果明天是阴天,我就穿衬衣: 如果明天是雨天,我就 ...

  5. Powershell Switch 条件

    Powershell Switch 条件 6 21 1月, 2012  在 Powershell tagged Powershell教程/ 分支/ 字符串/ 数字/ 条件by Mooser Lee 本 ...

  6. 选择结构switch

    1.选择结构switch switch 条件语句也是一种很常用的选择语句,它和if条件语句不同,它只能针对某个表达式的值作出判断,从而决定程序执行哪一段代码.例如,在程序中使用数字1~7来表示星期一到 ...

  7. Switch语句的参数是什么类型的?

    在Java5以前,switch(expr)中,exper只能是byte,short,char,int类型. 从Java5开始,java中引入了枚举类型,即enum类型. 从Java7开始,exper还 ...

  8. 带标签的循环语句、switch

    今天继续更新,控制流程的剩余部分内容,带标签的循环语句中的continue/break 的使用方法,以及switch关键字的使用方法.例1:带标签的continue/break.package com ...

  9. GoLang学习控制语句之switch

    基本结构 相比较 C 和 Java 等其它语言而言,Go 语言中的 switch 结构使用上更加灵活.它接受任意形式的表达式,例如: switch var1 { case val1: ... case ...

随机推荐

  1. [CF1526D] Kill Anton(逆序对,搜索)

    题面 A N T O N \rm ANTON ANTON 的基因由 A , N , T , O \rm A,N,T,O A,N,T,O 四种碱基排列组成. A N T O N \rm ANTON AN ...

  2. 动态规划——leetcode5、最长回文子串

    1.题目描述: 2.解题方法:动态规划 动态规划解题步骤: 1.确定状态 最后一步:如果s[i,...,j]是回文子串,那么需要满足两个条件 ① s[i] == s[j]: ② s[i+1,...,j ...

  3. 【Java】学习路径59-多个连接的服务器端

    ServerSocket可以对接多个Socket对象,利用这点,就可以实现:一台服务器对多个客户端. import java.io.IOException; import java.net.*; pu ...

  4. InnoDB_锁总结

    1. 查询会对资源添加共享锁 加了共享锁的资源不可以被修改:但可以被查询(也是会在资源上再加共享锁) 2. 数据修改会对资源添加排他锁 加了排他锁的资源只能被持有这个排他锁的事务读取和修改,其他事务读 ...

  5. 【设计模式】Java设计模式 - 适配器模式

    [设计模式]Java设计模式 - 适配器模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一 ...

  6. Python数据科学手册-机器学习之特征工程

    特征工程常见示例: 分类数据.文本.图像. 还有提高模型复杂度的 衍生特征 和 处理 缺失数据的填充 方法.这个过程被叫做向量化.把任意格式的数据 转换成具有良好特性的向量形式. 分类特征 比如房屋数 ...

  7. 【学习笔记】 Adaboost算法

    前言 之前的学习中也有好几次尝试过学习该算法,但是都无功而返,不仅仅是因为该算法各大博主.大牛的描述都比较晦涩难懂,同时我自己学习过程中也心浮气躁,不能专心. 现如今决定一口气肝到底,这样我明天就可以 ...

  8. 3_JavaScript

    一. 介绍 JavaScript语言诞生主要是完成页面的数据验证, 因此它运行在客户端, 需要运行浏览器来解析执行JavaScript代码 JS是弱类型, Java是强类型 特点 交互性(它可以做的就 ...

  9. PAT (Basic Level) Practice 1004 成绩排名 分数 20

    读入 n(>0)名学生的姓名.学号.成绩,分别输出成绩最高和成绩最低学生的姓名和学号. 输入格式: 每个测试输入包含 1 个测试用例,格式为 第 1 行:正整数 n 第 2 行:第 1 个学生的 ...

  10. 一文搞定 Spring事务

    Spring 事务 上文 使用SpringJDBC 1.JDBC事务控制 ​ 不管你现在使用的是那一种ORM开发框架,只要你的核心是JDBC,那么所有的事务处理都是围绕着JDBC开展的,而JDBC之中 ...