[英]NullPointerException through auto-boxing-behavior of Java ternary operator
前幾天我遇到了一個非常奇怪的NullPointerException
這是由三元運算符中的意外類型轉換引起的。 鑒於這個(無用的示例)功能:
Integer getNumber() {
return null;
}
我期望編譯后以下兩個代碼段完全相同:
Integer number;
if (condition) {
number = getNumber();
} else {
number = 0;
}
對比
Integer number = (condition) ? getNumber() : 0;
.
事實證明,如果condition
為true
,則if
語句工作正常,而第二個代碼段中的三元操作會拋出NullPointerException
。 似乎三元運算決定在將結果自動裝箱回Integer
之前將兩個選項都類型轉換為int
!?! 事實上,如果我顯式地將0
為Integer
,異常就會消失。 換句話說:
Integer number = (condition) ? getNumber() : 0;
不等同於:
Integer number = (condition) ? getNumber() : (Integer) 0;
.
因此,三元運算符和等效的if-else
語句之間似乎存在字節碼差異(這是我沒想到的)。 這就提出了三個問題:為什么會有差異? 這是三元實現中的錯誤還是類型轉換的原因? 鑒於存在差異,三元運算的性能是否比等效的if
語句更高或更低(我知道,差異不會很大,但仍然如此)?
根據JLS :-
條件表達式的類型確定如下:
- 如果第二個和第三個操作數具有相同的類型(可能是空類型),那么這就是條件表達式的類型。
- 如果第二個和第三個操作數之一是原始類型 T,另一個的類型是應用裝箱轉換的結果
(§5.1.7) 到 T,則條件表達式的類型為 T。
問題在於:
Integer number = (condition) ? getNumber() : 0;
強制對 getNumber() 的結果進行拆箱和重新裝箱。 這是因為三元 (0) 的 false 部分是整數,因此它嘗試將 getNumber() 的結果轉換為 int。 而以下不是:
Integer number = (condition) ? getNumber() : (Integer) 0;
這不是錯誤,只是 Java 選擇做事的方式。
這就是它應該如何工作。 三元運算符並不意味着等同於常規if
語句。 if
和else
的主體是語句,而后面的部分是?
和:
是表達式,需要計算為相同的類型。
換句話說: a = b ? c : d
a = b ? c : d
不應該等價於if (b) a = c; else a = d;
if (b) a = c; else a = d;
. 相反, b ? c : d
b ? c : d
本身就是一個表達式,將其結果賦值給a
不會影響結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.