簡體   English   中英

NullPointerException 通過 Java 三元運算符的自動裝箱行為

[英]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;

.

事實證明,如果conditiontrue ,則if語句工作正常,而第二個代碼段中的三元操作會拋出NullPointerException 似乎三元運算決定在將結果自動裝箱回Integer之前將兩個選項都類型轉換為int !?! 事實上,如果我顯式地將0Integer ,異常就會消失。 換句話說:

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語句。 ifelse的主體是語句,而后面的部分是? :表達式,需要計算為相同的類型。

換句話說: 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM