问:下面代码片段 func1 与 func2 在被调用时会如何执行?简单分析下原因?
public class Test {
public void func1() {
if ((Integer) null > 1) {}
}
public void func2() {
if ((Integer) null > 1) {
System.out.println("ABCDEFG");
}
}
}
答:上面代码段 func1、func2 在调用时都会抛出 NullPointerException
空指针异常。具体原因我们可以通过 javap 看编译后的 class 字节码,如下:
#javap -c Test
Compiled from "Test.java"
public class Test {
......
public void func1();
Code:
0: aconst_null
1: checkcast #5 // class java/lang/Integer
4: invokevirtual #6 // Method java/lang/Integer.intValue:()I
7: iconst_1
8: if_icmple 11
11: return
public void func2();
Code:
0: aconst_null
1: checkcast #5 // class java/lang/Integer
4: invokevirtual #6 // Method java/lang/Integer.intValue:()I
7: iconst_1
8: if_icmple 19
11: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
14: ldc #8 // String ABCDEFG
16: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
19: return
}
可以看到,作用在包装类型上的二元运算符会导致拆箱操作,拆箱的实质是调用包装类型对象的 intValue 方法,所以会抛出 NullPointerException
问题。
而 == 和 != 二元运算符在包装类型中比较特殊,需要区别对待,包装类型和基本类型进行 == 或者 != 运算时包装类型会自动拆箱变为基本型后再进行比较,而两个包装类型进行 == 或者 != 比较的是对象地址。具体变换案例如下:
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.func1();
test.func2();
}
//运行成功,if判断为 false
public void func1() {
if ((Integer) null == new Integer(1)) {}
}
//运行崩溃,NullPointerException 问题
public void func2() {
if ((Integer) null == 1) {
System.out.println("ABCDEFG");
}
}
}
问:下面语句能正常执行吗?
Integer test1 = (Integer) null;
Double test2 = (Double) null;
Boolean test3 = (Boolean) null;
答:上面语句可以正常执行。因为在 java 中 null 既不是对象也不是一种类型,它仅是一种特殊的值,我们可以将其赋予任何引用类型,也可以将 null 转化成任何类型。
本文参考自 Java 装箱与拆箱相关的空指针陷阱题解析