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 <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");
        }
    }
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。