switch case 当default在中间时,输出是什么?

看下面代码,当default在中间时,输出是什么?

public static void main(String[] args) {

    //当default在中间时,且看输出是什么?
    int a = 1;
    switch (a) {
    case 2:
        System.out.println("print 2");
    case 1:
        System.out.println("print 1");
    default:
        System.out.println("first default print");
    case 3:
        System.out.println("print 3");

}

是不是都被注释的内容影响到了?是的,这就是我们很容易忽略掉的点,switch...case的基本用法都忘了。。。

1.default就是如果没有符合的case就执行它,default并不是必须的.
2.case后的语句可以不用大括号.
3.switch语句的判断条件可以接受int,byte,char,short,不能接受其他类型(1.7以后支持String,以及上述四种包装类).
4.一旦case匹配,就会顺序执行后面的程序代码,而不管后面的case是否匹配,直到遇见break,利用这一特性可以让好几个case执行统一语句.

没有break时,匹配到一个之后就会将下面的所有的语句都执行!!!要根据自己的需要决定加不加break

下面是switch case底层剖析

1.首先我们知道JDK1.7及之后支持了String,也知道它是不支持null的,如下会出现NullPointException

    public static void main(String[] args) {
        String str = null;
        switch (str) {
            case "String":
                System.out.println("this is String");
            case "null":
                System.out.println("this is null String");
            case "帅":
                System.out.println("帅");
            default:
                System.out.println("this is default");
        }
    }

查看class文件如下

    public static void main(String[] args) {
        String str = "str";
        byte var3 = -1;
        switch(str.hashCode()) {
        case -1808118735:
            if (str.equals("String")) {
                var3 = 0;
            }
            break;
        case 24069:
            if (str.equals("帅")) {
                var3 = 2;
            }
            break;
        case 3392903:
            if (str.equals("null")) {
                var3 = 1;
            }
        }

        switch(var3) {
        case 0:
            System.out.println("this is String");
        case 1:
            System.out.println("this is null String");
        case 2:
            System.out.println("帅");
        default:
            System.out.println("this is default");
        }
    }

可以看到switch case对String的支持是因为做了hashCode以及equals,所以会出现NPE;然后又赋值给var3,对var3进行新的switch case

再对其进行反编译如下:可以看到两个关键的指令lookupswitch和tableswtich

 

2.lookupswitch和tableswitch

lookupswitch

     public static int test(int i) {
        int result;
        switch (i) {
            case 0:
                result = 0;
                break;
            case 2:
                result = 1;
                break;
            case 10:
                result = 4;
                break;
            default:
                result = -1;
        }
        return result;
     }

对应如下字节码

public static int test(int);
    Code:
       0: iload_0
       1: lookupswitch  { // 3
                     0: 36
                     2: 41
                    10: 46
               default: 51
          }
      36: iconst_0
      37: istore_1
      38: goto          53
      41: iconst_1
      42: istore_1
      43: goto          53
      46: iconst_4
      47: istore_1
      48: goto          53
      51: iconst_m1
      52: istore_1
      53: iload_1
      54: ireturn

tableswitch

    public static int test(int i) {

        int result;
        switch (i) {
            case 0:
                result = 0;
                break;
            case 2:
                result = 1;
                break;
            case 4:
                result = 4;
                break;
            default:
                result = -1;
        }
        return result;
    }

对应字节码

 public static int test(int);
    Code:
       0: iload_0
       1: tableswitch   { // 0 to 4
                     0: 36
                     1: 51
                     2: 41
                     3: 51
                     4: 46
               default: 51
          }
      36: iconst_0
      37: istore_1
      38: goto          53
      41: iconst_1
      42: istore_1
      43: goto          53
      46: iconst_4
      47: istore_1
      48: goto          53
      51: iconst_m1
      52: istore_1
      53: iload_1
      54: ireturn

首先看tableswitch和lookupswitch区别:

  • tableswitch使用了一个数组,通过下标可以直接定位到要跳转的行。但是在生成字节码时,有的行可能在源码中并不存在。通过这种方式可以获得O(1)的时间复杂度。(比如case 0 2 4,对应的字节码中case成了 0 1 2 3 4)
  •  
  • lookupswitch维护了一个key-value的关系,通过逐个比较索引来查找匹配的待跳转的行数。而查找最好的性能是O(log n),如二分查找。
    可见,通过用冗余的机器码,tableswitch换取了更好的性能。

但是,在分支比较少的情况下,O(log n)其实并不大。n=2时,log n 约为2.8;即使n=100, log n 约为 6.6,与1仍未达到1个数量级的差距。

另外Java虚拟机的tableswitch和lookupswitch指令只支持int类型,这也是为什么8种基本类型中只能支持char、byte、short、int .

因为 double、float 都是浮点类型的,tableswitch 和 lookupswitch 指令操作不了。

因为 long 类型 64 位了,而tableswitch 和 lookupswitch 指令只能操作 32 位的 int 。这两个指令对于 long 是搞不动的。

而至于 boolean 类型,还需要我说嘛?

你拿着 boolean 类型放到 switch 表达式里面去?

你就不能写个 if(boolean) 啥的?

 

参考https://www.cnblogs.com/wuyuegb2312/p/11172440.html

https://blog.csdn.net/csdnnews/article/details/108722499

 

我们知道 switch 的表达式和 case 里面都是不支持 null 的。

不过一个问题,switch/case 里面为什么不做成支持 null 的模式?

如果表达式为 null ,我们就拿着 null 去 case 里面匹配,这样理论上做也是可以做的,但是应该也不会有人问这个问题吧?谁知道能说下?或许只是设计者认为抛出空指针这样做比静默地跳过整个 switch 语句或选择在 default 标签(如果有)里面继续执行语句要好

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值