Java 自动拆箱引起的空指针异常

记录一次自己所犯的空指针异常错误,首先来看代码:

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 再对 Integerint 类型进行比较的时候又有一个自动拆箱的步骤,但是如果 number 变量为空,就会在自动拆箱的过程中抛出空指针异常。我们可以从字节码中看到更加具体的细节:

// class version 52.0 (52)
// access flags 0x21
public class Test {

  // compiled from: Test.java

  // access flags 0x1
  public ()V
   L0
    LINENUMBER 1 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object. ()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");
        }
    }
}

你可能感兴趣的:(Java 自动拆箱引起的空指针异常)