Java switch关键字原理及用法详解

 更新时间:2019年11月11日 16:51:16   作者:逸游Java  
这篇文章主要介绍了Java中 switch关键原理及用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

这篇文章主要介绍了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可以被编译为两种指令

  • 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,其他的只是编译器帮你进行了语法糖优化而已。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 详解spring boot配置 ssl

    详解spring boot配置 ssl

    本篇文章主要介绍了详解spring boot配置 ssl,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • java获取包下被指定注解的类过程解析

    java获取包下被指定注解的类过程解析

    这篇文章主要介绍了java获取包下被指定注解的类过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • SpringBoot瘦身打包部署的实现

    SpringBoot瘦身打包部署的实现

    这篇文章主要介绍了SpringBoot瘦身打包部署的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • 解决Nacos在执行startup.cmd的时候出现闪退的问题

    解决Nacos在执行startup.cmd的时候出现闪退的问题

    因为在工作中的项目中需要使用到nacos作为注册中心,但是在使用nacos的过程中运行startup.cmd的时候出现了闪退的情况,运行startup.cmd闪一下就没有了,我把解决这个问题的全过程理了一下,希望能帮到您,需要的朋友可以参考下
    2023-12-12
  • 基于SSM+Shiro+Bootstrap实现用户权限管理系统

    基于SSM+Shiro+Bootstrap实现用户权限管理系统

    这篇文章主要介绍了基于SSM+Shiro实现一个用户权限管理系统,每位用户只可访问指定的页面,文中的示例代码讲解详细,对我们学习或工作有一定帮助,快跟随小编一起学习吧
    2021-12-12
  • java内部类的那些事儿_让你一看就弄明白

    java内部类的那些事儿_让你一看就弄明白

    本篇文章介绍了,java内部类的那些事儿。需要的朋友参考下
    2013-05-05
  • RabbitMQ的安装和配置可视化界面的详细步骤

    RabbitMQ的安装和配置可视化界面的详细步骤

    这篇文章主要介绍了RabbitMQ的安装和配置可视化界面的详细步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • Springboot返回的json屏蔽某些属性的操作

    Springboot返回的json屏蔽某些属性的操作

    这篇文章主要介绍了Springboot返回的json屏蔽某些属性的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • Java将集合List转换成String字符串(或String转换成List)详解

    Java将集合List转换成String字符串(或String转换成List)详解

    今天在写项目的时候遇到一个问题,就是要把得到的一个集合转换成字符串,下面这篇文章主要给大家介绍了关于Java将集合List转换成String字符串(或String转换成List)的相关资料,需要的朋友可以参考下
    2023-06-06
  • java设计模式—静态代理模式(聚合与继承方式对比)

    java设计模式—静态代理模式(聚合与继承方式对比)

    下面小编就为大家带来一篇java设计模式—静态代理模式(聚合与继承方式对比)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05

最新评论