Object o1 = true ? new Integer(1) : new Double(2.0);
System.out.println(o1); // 輸出: 1.0 (而非預期的 1 或 1.0 區別在於類型)
Java 編譯器在編譯期確定三元運算符表達式的靜態類型,規則如下:
// 1. 操作數類型
new Integer(1) // 類型: Integer (包裝類)
new Double(2.0) // 類型: Double (包裝類)
// 2. 觸發規則 3: 均為數值包裝類型 -> 拆箱為基本類型 int 和 double
// 3. 基本類型二元數值提升: int + double -> double
// 4. 結果類型為基本類型 double -> 裝箱為 Double
// 5. 整個三元表達式靜態類型為 Double
// 6. 賦值給 Object o1: Double 向上轉型為 Object (多態)
// 7. 運行時: 條件 true -> 取值 new Integer(1) -> 但需符合表達式類型 Double
// -> 發生隱式拆箱 int -> 雙向數值提升為 double -> 裝箱為 Double(1.0)
// 8. 打印 o1 -> Double.toString() -> "1.0"
雖然條件為 `true` 選擇了 `Integer(1)`,但表達式的靜態類型已被編譯器確定為 `Double`,因此運行時必須將 `Integer` 值轉換為 `Double` (拆箱 → 提升 → 裝箱),最終存儲的是 `Double` 對象,值為 `1.0`。
// 情況 1: 同類型包裝類
Object o2 = true ? new Integer(1) : new Integer(2); // 類型 Integer, 輸出 1
// 情況 2: 基本類型
Object o3 = true ? 1 : 2.0; // 類型 double, 輸出 1.0
// 情況 3: 明確指定類型避免提升
Object o4 = true ? (Number)new Integer(1) : new Double(2.0); // 類型 Number, 輸出 1 (Integer 實例)
// 但注意: 這裡只是靜態類型變為 Number, 運行時仍是 Integer 實例, 打印 1
Object val = true ? String.valueOf(1) : String.valueOf(2.0); // 類型 String
true ? Integer : Double 結果為 `Double(1.0)` 是因為 Java 三元運算符編譯期類型推導遵循數值提升規則,將 `int` 和 `double` 提升為 `double`,最終表達式類型為 `Double`,運行時選擇的 `Integer` 值被強制轉換為 `Double`。理解 JLS 15.25 規則是避免此類陷阱的關鍵。