三目運算以及自動拆箱導致的NPE
System.out.println(false ? 1 : (Long)null); // NPE System.out.println(false ? Long.valueOf(1L) : (Long)null); System.out.println(false ? 1 : (String) null);
使用 javap -v 查看字節碼可以看到
9: invokevirtual #35 // Method java/lang/Long.longValue:()J 12: invokevirtual #39 // Method java/io/PrintStream.println:(J)V 15: getstatic #21 // Field java/lang/System.out:Ljava/io/PrintStream; 18: aconst_null 19: checkcast #33 // class java/lang/Long 22: invokevirtual #27 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 25: getstatic #21 // Field java/lang/System.out:Ljava/io/PrintStream; 28: aconst_null 29: checkcast #42 // class java/lang/String 32: invokevirtual #27 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
可以看到 " false ? 1 : (Long)null" 中對應的關鍵的代碼 Long.longValue(); 正式由於自動拆箱的操作導致了NPE;
當三目運算條件為false時,當":"左側為基本數據類型,而右側為基本類型的包裝類型時,則會引發包裝類型的自動拆箱操作;(這句話更完整的解釋為,當根據條件判斷時,如果選擇的表達式為基本類型的包裝類型,而未被選擇的表達式為基本類型,則選擇的結果會自動進行拆箱操作); 因此當 ((Long)null).longValue()被執行時則會拋出NPE
以下是官方文檔的解釋
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25
If one of the operands is of type T, where T is
Byte
,Short
, orCharacter
, and the other operand is a constant expression (§15.28) of typeint
whose value is representable in the type U which is the result of applying unboxing conversion to T, then the type of the conditional expression is U.