预防空指针
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 NullPointExceptionswitch (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_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnpublic static void main(java.lang.String[]);Code:0: aconst_null1: astore_12: aload_13: astore_24: iconst_m15: istore_36: aload_27: invokevirtual #2 // Method java/lang/String.hashCode:()I10: lookupswitch { // 13392903: 28default: 39}28: aload_229: ldc #3 // String null31: invokevirtual #4 // Method java/lang/String.equals:(Ljava/lang/Object;)Z34: ifeq 3937: iconst_038: istore_339: iload_340: lookupswitch { // 10: 60default: 71}60: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;63: ldc #3 // String null65: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V68: goto 7971: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;74: ldc #7 // String default76: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V79: 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_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: return
public static void main(java.lang.String[]); Code:
0: iconst_31: istore_12: iload_13: lookupswitch { // 13: 20default: 31}20: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;23: ldc #3 // String null25: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V28: goto 3931: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;34: ldc #5 // String default36: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V39: return
}
```
- 流程(比起上面的对象比较,少了
hashcode()和equals()判断)
lookupswitch有各个case值的 value (步骤3- 然后判断判断这个
param的 的范围- may use binary search
- 确定匹配哪个 case 后,跳转对应的代码块
- 执行代码块的真正逻辑
