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

Java 泛型通配符捕獲導致 ArrayList addAll 編譯失敗

     編輯:程式設計綜合問答

問題代碼

ArrayList<?> alist = new ArrayList<>();
ArrayList<?> blist = new ArrayList<>();
alist.addAll(blist); // 編譯錯誤
alist = blist;       // 賦值卻合法

錯誤信息

The method addAll(Collection<? extends capture#1-of ?>) in the type ArrayList<capture#1-of ?> is not applicable for the arguments (ArrayList<capture#2-of ?>)

核心原理

  • ArrayList<?> 中的 ? 代表未知類型,每次聲明都會生成獨立的捕獲類型(capture#1、capture#2)。
  • addAll 要求參數類型為 Collection<? extends E>,其中 E 是列表的元素類型。由於兩個列表的捕獲類型不同,編譯器無法確認類型兼容,拒絕編譯。
  • alist = blist 只是引用賦值,類型均為 ArrayList<?>,編譯器允許。

解決方案

  1. 明確具體類型(推薦):
    ArrayList<String> alist = new ArrayList<>();
    ArrayList<String> blist = new ArrayList<>();
    alist.addAll(blist); // 合法
    
  2. 使用有界通配符(若確實需要未知類型):
    ArrayList<? extends Object> alist = new ArrayList<>();
    ArrayList<? extends Object> blist = new ArrayList<>();
    // 仍無法 addAll,因捕獲類型仍不同
    // 必須轉型或用輔助方法
    
  3. 輔助方法繞過捕獲:
    
      public static <T> void safeAddAll(List<T> dest, List<? extends T> src) {
          dest.addAll(src);
      }
      // 調用
      safeAddAll(alist, blist); // 編譯器推導 T 為 Object
      

最佳實踐

避免在集合聲明中使用無界通配符 List<?> 作為可變容器。僅在只讀參數(如 void print(List<?> list))中使用。寫入操作請明確泛型參數。

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