当前位置 主页 > 网站技术 > 代码类 >

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

    栏目:代码类 时间:2019-11-11 21:06

    这篇文章主要介绍了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");
      }
     }