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

Java 每日一題:泛型類型推導與多態——List<?> 能否存入 Integer 和 Double?

     編輯:Java 綜合教學

Java 每日一題:泛型類型推導與多態——List<?> 能否存入 Integer 和 Double?

題目來源:【Java每日一題】20170117

代碼片段

package Jan2017;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Ques0117 {
    public static void main(String[] args) {
        List list = Ques0117.asList(1, 2, 3.0);
    }

    public static  List asList(T... t) {
        List list = new ArrayList();
        Collections.addAll(list, t);
        return list;
    }
}

問題

  1. 主程序能否正常編譯?
  2. list 的泛型參數類型是什麼?是 Number 嗎?

解析

1. 編譯結果:✅ 正常編譯

調用 asList(1, 2, 3.0) 時,實參類型為 int, int, double。經過自動裝箱變為 Integer, Integer, Double。

Java 泛型類型推導機制會尋找所有實參的最特化公共超類型(Least Upper Bound, LUB)。

  • Integer 繼承 Number 實現 Comparable<Integer>, Serializable
  • Double 繼承 Number 實現 Comparable<Double>, Serializable
  • LUB = Number & Comparable<?> & Serializable(交集類型)

因此推導出的 T 為 Number & Comparable<?> & Serializable,而非單純的 Number。

2. 變量聲明:List list(原始類型)

代碼中聲明 List list(無泛型參數),屬於原始類型,編譯器會發出「未檢查」警告,但合法。若改為 List<Number> list = ... 則編譯錯誤,因為 List<Number & Comparable<?> & Serializable> 不是 List<Number> 的子類型(泛型不變性)。

3. 運行時行為

由於類型擦除,運行時 list 就是 ArrayList,實際存儲 Integer, Integer, Double 三個對象,獲取時無需強轉(原始類型視為 Object)。

關鍵知識點

  • 類型推導:Java 8 目標類型推導;Java 7 需顯式指定 <Number>asList(...) 或賦值給 List<Number> 觸發推導。
  • LUB 計算:lub(T1, T2) = 最小公共超類型,包含所有共同接口。
  • 交集類型:Number & Comparable<?> & Serializable 只能作為類型參數或強轉目標,不能作為變量聲明類型(Java 語法限制)。
  • 原始類型風險:使用原始類型 List 繞過泛型檢查,失去類型安全,不推薦。

最佳實踐

// 明確指定類型參數
List list = Ques0117.asList(1, 2, 3.0); // 編譯通過,T=Number

// 或使用顯式構造
List list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3.0); // 自動裝箱為 Number 子類

理解泛型推導規則與 LUB,能避免「為什麼這裡推導出這個怪異類型」的困惑,編寫更精確的泛型代碼。

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