首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

J2SE 核心陷阱:條件運算子(三元運算子)型別推導規則深度解析

     編輯:Java 相關知識

條件運算子 booleanExp ? exp1 : exp2 看似簡單,其結果型別推導規則卻藏著許多 Java 開發者易踩的坑。本文依據 JLS(Java Language Specification)條文,配合實測程式碼,系統拆解三大規則與邊界情況。

三大型別推導規則(JLS §15.25)

  1. 同型則該型:exp1、exp2 型別相同 → 結果為該型別。
  2. 常數窄化轉換:一邊為 byte/short/char(稱 T),另一邊為 int 常數運算式 且值在 T 範圍內 → 結果為 T。
  3. 雙向數值提升:其餘情況 → 依數值提升規則(byte/short/char → int → long → float → double)提升至較寬型別。

實測案例分析

char x = 'A';      // 65
int i = 0;

System.out.println(true ? x : 0);        // 輸出 'A' (char)
System.out.println(true ? x : 1111111110); // 輸出 65 (int)
System.out.println(false ? i : x);       // 輸出 65 (int)

逐行解析

運算式exp1 型別exp2 型別規則匹配結果型別輸出
true ? x : 0charint 常數 (0)規則 2:0 在 char 範圍內char'A'
true ? x : 1111111110charint 常數 (超出 char 範圍)規則 3:char → int 提升int65
false ? i : xint 變數char 變數規則 3:無常數,雙向提升int65

關鍵差異:0 是編譯期常數,i 是變數。常數允許窄化,變數不允許。

物件參考型別情況

Test t = false ? new Object() : new Test(); // 編譯錯誤
  • exp1:Object,exp2:Test(假設 Test extends Object)。
  • 無常數運算式,型別不同 → 規則 3:提升至共同父類 Object。
  • 結果型別 Object 無法指派給 Test 變數 → 編譯錯誤。

修正:強制轉型 (Test) (false ? new Object() : new Test()) 或調整邏輯避免此結構。

實戰防坑檢查清單

  1. 混用基本型別與包裝類別:true ? 1 : Integer.valueOf(2) → 自動拆箱提升為 int,但 null 會拋 NPE。
  2. 長整數字面值:true ? 1 : 1L → 結果 long,賦給 int 需強制轉型。
  3. 字串與非字串:true ? "A" : 1 → 非字串端 toString() 後結果 String(特殊規則)。
  4. 副作用陷阱:condition ? methodA() : methodB() 只執行一邊,若依賴副作用需改用 if-else。

結語

條件運算子型別推導遵循「常數優先窄化、否則雙向提升」原則。理解 編譯期常數 與 變數 的本質差異,是避免「明明型別相容卻編譯失敗」或「運行時意外拆箱 NPE」的關鍵。寫法複雜時,寧可拆成 if-else 明確標註型別,亦可加強可讀性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved