记录一次自己所犯的空指针异常错误,首先来看代码:
public class Test {
public void fun(Integer number) {
if (number == 1) {
System.out.println("This number is 1");
} else {
System.out.println("This number is not 1");
}
}
}
在这段代码中,if
里边的判断条件有着抛出空指针异常的风险,其主要的原因是因为 Java 再对 Integer
与 int
类型进行比较的时候又有一个自动拆箱的步骤,但是如果 number
变量为空,就会在自动拆箱的过程中抛出空指针异常。我们可以从字节码中看到更加具体的细节:
// class version 52.0 (52)
// access flags 0x21
public class Test {
// compiled from: Test.java
// access flags 0x1
public <init>()V
L0
LINENUMBER 1 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this LTest; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1
public fun(Ljava/lang/Integer;)V
L0
LINENUMBER 3 L0
ALOAD 1
INVOKEVIRTUAL java/lang/Integer.intValue ()I
ICONST_1
IF_ICMPNE L1
L2
LINENUMBER 4 L2
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "This number is 1"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
GOTO L3
L1
LINENUMBER 6 L1
FRAME SAME
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "This number is not 1"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L3
LINENUMBER 8 L3
FRAME SAME
RETURN
L4
LOCALVARIABLE this LTest; L0 L4 0
LOCALVARIABLE number Ljava/lang/Integer; L0 L4 1
MAXSTACK = 2
MAXLOCALS = 2
}
在上述的字节码中 INVOKEVIRTUAL java/lang/Integer.intValue ()I
清楚的表示了这一过程。
因此在日常编码的过程中,对于包装类型的比较需要进行额外的空判断,如下所示:
public class Test {
public void fun(Integer number) {
if (number != null && number == 1) {
System.out.println("This number is 1");
} else {
System.out.println("This number is not 1");
}
}
}