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

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

(0)

相关推荐

  • java中switch case语句需要加入break的原因解析

    java中switch case语句需要加入break的原因解析            java 中使用switch case语句需要加入break 做了具体的实例分析,及编译源码,在源码中分析应该如何使用,大家可以参考下: 假设我们有如下这样一个switch语句: public static void test(int index) { switch (index) { case 1: System.out.println(1); case 2: System.out.println(2);

  • java 学习笔记(入门篇)_多选择结构switch语句

    多选择结构switch语句 在java中为多路分支选择流程专门提供了switch语句,switch语句根据一个表达式的值,选择运行多个操作中的一个.他的语法形式如下: 复制代码 代码如下: switch(表达式){ case 表达式常量1:语句1: break: case 表达式常量2:语句2: break: ...... case 表达式常量n:语句n: break: [default:语句n+1:] } 其中,一个case表达式常量成为标号,代表一个case分支的入口.switch语句在运行

  • java中switch选择语句代码详解

    switch结构(开关语句)的语法 switch(表达式 ){ --->类型为int.char case 常量1 :--->case 结构可以有多个 //语句块1 break; --->程序跳出switch结构 case 常量n :--->常量的值不能相同 //语句块n break; default:--->和if结构中的 else作用相同 //语句块 break; } 下面看一段代码示例,有详细的注释,大家可以参考: public class SwitchStu{ /* s

  • java switch语句使用注意的四大细节

    switch语句的格式如下:(它的功能是选出一段代码执行) 复制代码 代码如下: switch(整数选择因子) { case 整数值1 : 语句; break; case 整数值2 : 语句; break; case 整数值3 : 语句; break; case 整数值4 : 语句; break; case 整数值5 : 语句; break; ... default:语句; } 但是要注意几点如下: 1.switch中case的参数类型只能是int类型,但是放byte,short,char类型的

  • Java语法基础之选择结构的if语句、switch语句详解

    [前言] 流程控制语句: 在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的.也就是说程序的流程对运行结果有直接的影响.所以,我们必须清楚每条语句的执行流程.而且,很多时候我们要通过控制语句的执行顺序来实现我们要完成的功能. 流程控制语句分类: 顺序结构选择结构:if语句.switch语句循环结构:while语句.for语句 一.顺序结构: 是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的. 总的来说:写在前面的

  • Java控制语句之if、switch语句

    java if语句 Java控制语句分为三大类:①顺序结构:②选择结构:③循环结构. -------------------------------------------------------------------------------- 选择结构又分为:①单选择结构:②双选择结构:③多选择结构. 主要涉及: if_else , switch , while , break 和 continue , for. if单选择结构 对条件表达式进行一次测试,若测试为真,则执行下面的语句,否则跳

  • Java中switch判断语句典型使用实例

    下面一个是典型的switch语法运用的例子. import java.util.Scanner; public class JudgeMonth { public static void main(String[] arg){ Scanner scan = new Scanner(System.in); System.out.println("请输入月份:"); int month = scan.nextInt(); switch(month){ case 12: case 1: ca

  • Java中Switch用法代码示例

    一.java当中的switch与C#相比有以下区别 注:在java中switch后的表达式的类型只能为以下几种:byte.short.char.int(在Java1.6中是这样),  在java1.7后支持了对string的判断 还有一点要注意的是:在java中如果switch的case语句中少写了break;这个关键字,在编译的时候并没有报错.但是在执行的时候会一直执行所有case条件下的语句并不是去判断,所以会一直执行直到遇到break关键字跳出或者一直执行到defaut语句. 还有就是如果

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

    这篇文章主要介绍了Java中 switch关键原理及用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的一个主要原因就在于它的作用能被if-else代替,况且switch对类型的限制,也阻碍了switch的进一步使用. 先看看switch的语法

  • Java访问权限原理与用法详解

    本文实例讲述了Java访问权限原理与用法.分享给大家供大家参考,具体如下: 构造者模式思想 进行初始化,解决了多个构造器重载,构造器参数过多记不住的情况. package day7;//声明一个程序包 class Employee{ private String name; private int no; private int age; private String sex; private String address; //alt + shift + s public int getNo(

  • Java泛型继承原理与用法详解

    本文实例讲述了Java泛型继承原理与用法.分享给大家供大家参考,具体如下: 一 点睛 当创建了带泛型声明的接口.父类之后,可以为该接口创建实现类,或从该父类来派生子类,但值得指出的是,当使用这些接口.父类时不能再包含类型形参. 如果使用泛型类时没有传入实际的类型参数,Java编译器可能发出警告:使用了未经检查或不安全的操作--这就是泛型检查的警告. 二 实战--传入实际的类型参数 public class A1 extends Apple<String> { // 正确重写了父类的方法,返回值

  • Java 反射机制原理与用法详解

    本文实例讲述了Java 反射机制原理与用法.分享给大家供大家参考,具体如下: 反射反射,程序员的快乐! 1.什么是反射? Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:并且能改变它的属性.而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是

  • Java重载构造原理与用法详解

    本文实例讲述了Java重载构造原理与用法.分享给大家供大家参考,具体如下: 带参数方法 [1]无参数,无返回值 void 方法名(){方法体:} [2]无参数,有返回值 int 方法名(){方法体:} [3]有参数,无返回值 void 方法名(int num){方法体:} [4]有参数,有返回值 int 方法名(int num){方法体:} 可变参数与数组参数的区别 [1]可变参数传参灵活,,可以无参,可以多个参数,可以数组:   数组参数只能传递数组 [2]可变参数必须放在最后   数组可以放

  • Java循环队列原理与用法详解

    本文实例讲述了Java循环队列原理与用法.分享给大家供大家参考,具体如下: 在正式进行循环队列学习之前,我们先来看看在顺序队列中删除队首元素出现的问题 (1)设一个容量为capacity=8,size=5(a,b,c,d,e)的数组,左侧为队首.右侧为队尾. (2)出队一个元素后,需整体往前移动一位 #出队 #2整体前移一位 关于该种操作方式我们很容易得出时间复杂度为O(n). 这时我们就想可不可以在出队元素后,整体元素不往前移,而是在数组中记下队首front是谁,同时队尾tail指向在下一次元

  • Java基础之Stream流原理与用法详解

    目录 一.接口设计 二.创建操作 三.中间操作 四.最终操作 五.Collect收集 Stream简化元素计算 一.接口设计 从Java1.8开始提出了Stream流的概念,侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式:依旧先看核心接口的设计: BaseStream:基础接口,声明了流管理的核心方法: Stream:核心接口,声明了流操作的核心方法,其他接口为指定类型的适配: 基础案例:通过指定元素的值,返回一个序列流,元素的内容是字符串,并转换为Long类型,最终计算求和结果并

  • Java this 关键字的使用方法详解

    Java this 关键字的使用方法详解 构造方法中的this关键字 构造方法是一个类的对象在通过new关键字创建时自动调用的,在程序中不能向调用其他方法一样通过方法名(也就是类名)来调用.但如果一个类有多个构造方法,可以在一个构造方法中通过this(paras-)来调用其他的构造方法. 使用this来调用其他构造方法有如下几个约束. 1) 只能在构造方法中通过this来调用其他构造方法,普通方法中不能使用. 2) 不能通过this递归调用构造方法,即不能在一个构造方法中通过this直接或间接调

  • 浅谈java Iterator.remove()方法的用法(详解)

    实例如下: @Test public void tt(){ List<String> list = new ArrayList<String>(); list.add( "0" ); list.add( "1" ); list.add( "2" ); list.add( "3" ); list.add( "4" ); list.add( "5" ); list.a

  • C语言switch使用之诡异用法详解

    关于switch的用法这里不再做什么总结了,其实这个是一个便捷的快速跳转条件切换器.而关于这个功能最常用的技术讨论点在于case后面的break以及default.这里不讨论这些,直接看下面的代码: #include"stdio.h" int main(void) { int num = 0; switch(num) { printf("functionrun!\n"); } return 0; } 上面的代码中用到了一个switch,但是代码块中没有任何case以

随机推荐