看一段代码,这是一道试题,思考一下,结果是什么?为什么?
package cn.com.suntree.utils.myself;
public class SwitchTest {
public static void main(String[] args) {
String paramStr = null;
switch (paramStr){
case "boy":
break;
case "girl":
System.out.println("is a girl ");
break;
case "null":
System.out.println("is a null ");
break;
default:
System.out.println("is a nothing ");
}
}
}
我们知道,在jdk1.7之前,switch只接收一个整型表达式,后面扩展了,支持字符串
怎么做到的,由于switch不是方法,没法直接看源码,我们将代码反编译来看看
找到字节码所在文件,用java自带命令
javap -c SwitchTest >switch.dcmp
获取到反编译代码
Compiled from "SwitchTest.java"
public class cn.com.suntree.utils.myself.SwitchTest {
public cn.com.suntree.utils.myself.SwitchTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: aconst_null
1: astore_1
2: aload_1
3: astore_2
4: iconst_m1
5: istore_3
6: aload_2
7: invokevirtual #2 // Method java/lang/String.hashCode:()I
10: lookupswitch { // 3
97740: 44
3173020: 58
3392903: 72
default: 83
}
44: aload_2
45: ldc #3 // String boy
47: invokevirtual #4 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
50: ifeq 83
53: iconst_0
54: istore_3
55: goto 83
58: aload_2
59: ldc #5 // String girl
61: invokevirtual #4 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
64: ifeq 83
67: iconst_1
68: istore_3
69: goto 83
72: aload_2
73: ldc #6 // String null
75: invokevirtual #4 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
78: ifeq 83
81: iconst_2
82: istore_3
83: iload_3
84: tableswitch { // 0 to 2
0: 112
1: 115
2: 126
default: 137
}
112: goto 145
115: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
118: ldc #8 // String is a girl
120: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
123: goto 145
126: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
129: ldc #10 // String is a null
131: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
134: goto 145
137: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
140: ldc #11 // String is a nothing
142: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
145: return
}
指令看不懂没关系,能看懂这句就行
也就是说,虽然switch能接收String字符串,但在jvm的实现时,还是取了字符串的hashCode来进行操作
字符串的hashCode方法
它返回的还是一个int类型的整数,委婉的转换成了int
所以回到问题,我们的paramStr为null对象,那自然在做 hashCode()是会报空指针异常
运行一下结果,完全符合预期
所以关于switch接收字符串能运行的原因,你明白了吗?