写在前面:初中肄业文化水平,如有不足欢迎指正。

switch语句作为一种选择语句,也被称为开关语句,实际开发时由于自己能力问题很少选择该语句作为方案。相比ifelse语句,switch无疑在逻辑展示方面更加的清晰,如果遇到固定值的多重判断时,switch应该是大多情况的首选方案。

switch(表达式){
 case 值1:
  代码块1;
  break;
 case 值2:
  代码块2;
  break;
 case 值3:
  代码块3;
  break;
 ...........
  default:
   默认执行;
}

1.switch根据不同的情况会有不同的格式变化,首先是最常见的贯穿:

public class DemoSwithCase {
    public static void main(String[] args) {
        int 贯穿数字 = 7;
        switch (贯穿数字){
            case 7:
                贯穿数字++;//执行自增 7-》8
            case 8:
                贯穿数字++;//执行自增 8-》9
            case 9:
                贯穿数字++;//执行自增 9-》10
            default:
                System.out.println(贯穿数字);// result:10
        }
    }
}

2.switch在JDK1.7(老年人了,叫的正规见谅)以后可以判断String类型的对象了

 1  public static void main(String[] args) {
 2         String area = "China";
 3         switch (area){
 4             case "China":
 5                 System.out.println("China!");//输出:China!
 6                 break;
 7             case "Japan":
 8                 System.out.println("Japan!");
 9                 break;
10             case "English":
11                 System.out.println("English!");
12                 break;
13             default:
14                 System.out.println("钓鱼岛是中国的!");
15                 break;
16         }
17     }

但是这样做判断有一个明确的规定就是case和小括号里面不能写null;

好奇宝宝就想知道为什么在这两处不能写null,于是试着用idea的jclasslib插件查看字节码详情

  0 ldc #2 <China> //int取值
  2 astore_1  //出栈 赋值给局部变量表对应数组下标为1的元素
  3 aload_1  //进栈 当前局部变量表对应数组下标为1的元素
  4 astore_2  //出栈
  5 iconst_m1  //int 常量值-1进栈
  6 istore_3  
  7 aload_2
  8 invokevirtual #3 <java/lang/String.hashCode>   //调用引用类型的方法的引用 这里调用了String.hashCode方法
 11 lookupswitch 3    //switch语句对应字节码:备用开关,非紧凑情况使用,带键值标签
    60895824:  72 (+61)  //这里就可以看到String类型实际在JVM执行时是采用hashcode值比较的
    65078583:  44 (+33)
    71341030:  58 (+47)
    default:  83 (+72)
 44 aload_2
 45 ldc #2 <China>
 47 invokevirtual #4 <java/lang/String.equals>
 50 ifeq 83 (+33)
 53 iconst_0
 54 istore_3
 55 goto 83 (+28)
 58 aload_2
 59 ldc #5 <Japan>
 61 invokevirtual #4 <java/lang/String.equals>
 64 ifeq 83 (+19)
 67 iconst_1
 68 istore_3
 69 goto 83 (+14)
 72 aload_2
 73 ldc #6 <English>
 75 invokevirtual #4 <java/lang/String.equals>
 78 ifeq 83 (+5)
 81 iconst_2
 82 istore_3
 83 iload_3
 84 tableswitch 0 to 2    0:  112 (+28)
    1:  123 (+39)
    2:  134 (+50)
    default:  145 (+61)
112 getstatic #7 <java/lang/System.out>
115 ldc #8 <China!>
117 invokevirtual #9 <java/io/PrintStream.println>
120 goto 153 (+33)
123 getstatic #7 <java/lang/System.out>
126 ldc #10 <Japan!>
128 invokevirtual #9 <java/io/PrintStream.println>
131 goto 153 (+22)
134 getstatic #7 <java/lang/System.out>
137 ldc #11 <English!>
139 invokevirtual #9 <java/io/PrintStream.println>
142 goto 153 (+11)
145 getstatic #7 <java/lang/System.out>
148 ldc #12 <钓鱼岛是中国的!>
150 invokevirtual #9 <java/io/PrintStream.println>
153 return

从上面的字节码大致可以分析到一些结果,首先switch语句在JVM执行时无论判断的对象是什么类型,最后都会转变为以一个int类型的数值来比较,并返回比较结果。

那么当String的对象为null时,该对象不存在对应的hashCode值,也就无法作为equals的比较中的任何一方,最后导致空指针异常

并且由于在JVM解析switch语句时会首先获得判断对象的hashCode值,所以在这个时候异常就出现了。

String area = null;
        switch (area){//NullPointerException
            case "China":
                System.out.println("China!");//输出:China!
                break;
            case "Japan":
                System.out.println("Japan!");
                break;
            case "English":
                System.out.println("English!");
                break;
            default:
                System.out.println("钓鱼岛是中国的!");
                break;
        }

以上就是好奇宝宝的第一次探险经历总结。不得不说,java还是有很多细节和特性等待宝宝去慢慢挖掘der。

12-20 20:41
查看更多