我的问题是基于上一个问题的答案:
Why we can't do List<Parent> mylist = ArrayList<child>();
我有一个函数可以根据父函数中的参数对传递给它的子项列表进行排序。由于有许多不同类型的孩子,我编写了一个接收通用父类型的函数。
void sort(ArrayList<? extends Parent> passedList)
稍后在函数中,我想交换ArrayList的两个成员(i和j),但我无法弄清楚如何。我试过了:
Parent swap;
swap = passedList.get(i);
passedList.set(i,passedList.get(j));
passedList.set(j,swap);
然而,这将无法编译,并且它表示类型在set函数中不兼容。我从get获得的类型是Parent,但是set期望一种类型(?extends Parent)。我也尝试将交换声明为? extends Parent swap;
或通过转换为
passedList.set(i,(? extends Parent)passedList.get(j));
似乎应该可以看到我们如何保证passList.get()返回的对象是属于arraylist的正确类型。
答案 0 :(得分:1)
<? extends Parent>
承诺该列表是包含Parents
的列表,或包含Parent
子类的列表,例如ArrayList<Child>
。
这意味着您始终可以将对象视为Parent
,但您无法将Parent
放回其中,因为实际的列表类型可能不是{{1} (并且您无法在Parent
中添加Parent
)。
答案 1 :(得分:1)
似乎应该可以看到我们如何保证passList.get()返回的对象是属于arraylist的正确类型。
我们可以说它是正确的,因为我们可以查看代码并追溯swap
来自哪里。但编译器无法分辨,因为语言无法保证。您正尝试将Parent
放入List<? extends Parent>
,该列表可能是某种子类型,例如List<Child>
。
相反,您可以通过通配符捕获来实现此目的:
static <P extends Parent> void swap(List<P> list, int i, int j) {
P temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
这使您可以表示temp
的类型与list
的实际类型参数相同。
另见: