预防空指针
Switch 的空指针问题
switch 匹配哪些参数?
java8
- 引用数据类型
- String
- Character
- Integer
- Short
- Byte
- 基本数据类型
- char
- int
- short
- byte
switch 流程
switch(param is Object) 流程
- 当参数是引用类型时
代码
public static void main(String[] args) {
Integer str = null;
// cost NullPointException
switch (str) {
case 2:
System.out.println("null");
break;
default:
System.out.println("default");
}
}
反编译
javap -c <classFile>
public class list5.NullTest {
public list5.NullTest();
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 { // 1
3392903: 28
default: 39
}
28: aload_2
29: ldc #3 // String null
31: invokevirtual #4 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
34: ifeq 39
37: iconst_0
38: istore_3
39: iload_3
40: lookupswitch { // 1
0: 60
default: 71
}
60: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
63: ldc #3 // String null
65: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
68: goto 79
71: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
74: ldc #7 // String default
76: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
79: return
}
- 流程
- 先计算
switch(param)
中param
的参数的hashCode
比如上面的步骤7 (这一步就可能导致NullPointException
) lookupswitch
有各个case
值的hashcode
(步骤10- 然后判断判断这个
param
的hashcode
的范围- may use binary search
- 确定匹配哪个 case 后,跳转对应的代码块
- 再判断对象是否相等 (步骤31, 34
- 再执行代码块的真正逻辑
switch(param extends Object) 流程
代码
public static void main(String[] args) {
int str = 3;
switch (str) {
case 3:
System.out.println("null");
break;
default:
System.out.println("default");
}
}
反编译 ```shell public class list5.NullTest { public list5.NullTest(); Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]); Code:
0: iconst_3
1: istore_1
2: iload_1
3: lookupswitch { // 1
3: 20
default: 31
}
20: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
23: ldc #3 // String null
25: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
28: goto 39
31: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
34: ldc #5 // String default
36: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
39: return
}
```
- 流程(比起上面的对象比较,少了
hashcode()
和equals()
判断)
lookupswitch
有各个case
值的 value (步骤3- 然后判断判断这个
param
的 的范围- may use binary search
- 确定匹配哪个 case 后,跳转对应的代码块
- 执行代码块的真正逻辑