美文网首页
if-else 和 switch的区别

if-else 和 switch的区别

作者: Bug之王 | 来源:发表于2021-03-08 21:24 被阅读0次

    一直以为if-else和switch除了形式上不太一样外效果应该是完全一样的,直到看到《Java编程的逻辑》的关于switch的内容时才发现还是有一点区别的。

    如下if-else 代码:

    public static void main(String[] args) {
            int num1 = 2;
            int num2;
            if (num1 == 1) {
                num2 = 1;
            } else if (num1 == 2) {
                num2 = 2;
            } else {
                num2 = 3;
            }
            System.out.println(num2);
        }
    

    通过javap -c命令查看字节码

    public static void main(java.lang.String[]);
        Code:
           0: iconst_2                              //常量2入操作数栈
           1: istore_1                              //操作数栈出栈,并赋值给第一个变量(num1)
           2: iload_1                               //第一个变量(num1)的值入操作数栈
           3: iconst_1                             //常量1入操作数栈
           4: if_icmpne     12                  //条件跳转:栈顶的两个值不相等则跳转到12行
           7: iconst_1                             //常量1入操作数栈
           8: istore_2                             //操作数栈出栈,并赋值给第二个变量(num2)
           9: goto          24                    //跳转到24行
          12: iload_1                            //第一个变量(num1)的值入操作数栈
          13: iconst_2                         //常量2入操作数栈
          14: if_icmpne     22              //条件跳转:栈顶的两个值不相等则跳转到22行
          17: iconst_2                         //常量1人操作数栈
          18: istore_2                         //操作数栈出栈,并赋值给第二个变量(num2)
          19: goto          24                 //跳转到24行
          22: iconst_3                         //常量2入操作数栈
          23: istore_2                         //操作数栈出栈,并赋值给第二个变量(num2)
          24: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
          27: iload_2
          28: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
          31: return
    

    0 ~ 1:给变量num1赋值
    2 ~ 4:对应if行,当num1不等于2时,跳转到12行,也就是对应else if判断的那一行
    7 ~ 8:给num2赋值,当条件跳转语句(第4行)没有跳转时执行
    9:无条件跳转到24行,也就是if-else整体结束后的语句,这就是if-else语句只会执行一个子句的原因。
    12 ~ 14:对应else-if判断,同2 ~ 4
    17 ~ 18:给num2赋值,同7 ~ 8
    19:无条件跳转,同9
    22 ~ 23:给num2赋值,同7 ~ 8

    通过上述代码可以看出if-else 语句主要是通过条件跳转指令和无条件跳转指令控制整个流程的,如果有多个子句,是需要多次判断,直到符合条件。

    下面是相同效果的switch语句:

    public static void main(String[] args) {
            int num1 = 2;
            int num2 = 3;
            switch (num1) {
                case 1:
                    num2 = 1;
                    break;
                case 2:
                    num2 = 2;
                    break;
            }
            System.out.println(num2);
        }
    
    public static void main(java.lang.String[]);
        Code:
           0: iconst_2
           1: istore_1
           2: iload_1
           3: lookupswitch  { // 2
                         1: 28
                         2: 33
                   default: 38
              }
          28: iconst_1
          29: istore_2
          30: goto          40
          33: iconst_2
          34: istore_2
          35: goto          40
          38: iconst_3
          39: istore_2
          40: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
          43: iload_2
          44: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
          47: return
    

    可以看出字节码代码和if-else的完全不同,其通过lookupswitch(或者tableswitch)将条件集中在了一起,一个条件对应一个执行代码的行数,条件对应的执行逻辑在条件下边。tableswitch维护了一个数组,将switch语句传入的值作为下标找到要执行代码的行数;lookupswitch维护了一组key-value值,key排序,将switch语句传入的值作为目标值通过二分查找可以找到要执行的语句。可见对比if-else,性能上可以从O(n)提升到O(logn)或者O(1)。
    另外,注意30和35行的跳转命令,对应我们的break语句,这就是为什么switch语句要写break语句的原因。

    相关文章

      网友评论

          本文标题:if-else 和 switch的区别

          本文链接:https://www.haomeiwen.com/subject/jqhmqltx.html