为什么不能列出<! - ?扩展List <T - >&gt;被分配到List <list <t>&gt;

时间:2017-04-04 06:09:04

标签: java generics

我的班级有一个属性,它是某个班级T的二维列表。

似乎将此属性创建为List<? extends List<T>>是合乎逻辑的,因此除了List<ArrayList<T>>之外,还可以为其分配List<LinkedList<T>List<List<T>>

我的getter返回List<List<T>>似乎也是合乎逻辑的,因为我们不需要告诉消费者这个列表可以分配什么,因为消费者会将他从getter获取的对象指向变量,而不是相反。

但是,我的getter拒绝自动将List<? extends List<T>>转换为List<List<T>>,从而引发IncompatibleType错误。为什么不能强迫它?

1 个答案:

答案 0 :(得分:1)

@JB-Nizet很好地解释了原因:它允许您将ArrayList添加到LinkedList -s列表中。

简短的回答当然是你不能这样做,因为编译器不允许你这样做;)

让我再举一个例子。您基本上无法向此类集合添加任何内容:

List<? extends List<T>> list = new ArrayList<>();
list.add(new LinkedList<T>()); // compile error
list.add(new ArrayList<T>()); // compile error
List<T> sublist = new ArrayList<>();
list.add(sublist); // compile error

如果这是您想要的,那么您可以在getter中使用任何列表类型并返回通配符类型:

public List<? extends List<T>> getSomething() {
    List<ArrayList<T>> list = new ArrayList<>();
    // do something
    return list; // List<ArrayList<T>> converts automatically to List<? extends List<T>
}

如果您希望客户添加内容但未删除,则可以使用super关键字:

List<? super ArrayList<T>> list = new ArrayList<>();
list.add(new ArrayList<T>()); // this is fine

另一方面,如果你想允许这两个操作,那么就不要使用通配符:

public List<List<T>> getSomething() {
    return new ArrayList<>();'
}