我有以下代码:
public static void swap(List<?> list) {
swapHelper(list); //1
}
private static <E> void swapHelper(List<E> list) {
swap(list); //2
}
{
List<?> tW = new ArrayList<>();
List<E> tE = new ArrayList<>();
tW = tE; // 3
tE = tW; // 4
}
在此代码行1和2中成功编译,并不意味着:
我可以将List<?>
的引用分配给List<E>
的引用,反之亦然?
如果是这样,那么为什么第4行不能编译。
答案 0 :(得分:-2)
<?>
和<E>
都是未知类型;但是所有List<?>
都有某些类型的元素,因此您可以调用参数为List<E>
的方法,因为有一些未知类型与之匹配。
请注意,您无法执行此操作:
public static void swap(Object object, List<?> list) {
swapHelper(object, list); // Compiler error: object not in bounds of list.
}
private static <E> void swapHelper(E object, List<E> list) {
swap(object, list); // OK.
}
因为您现在不知道Object
是否在List<?>
的范围内。
您也不能在列表中添加新的非空值:
private static <E> void swapHelper(List<E> list) {
list.add(new E()); // Can't create an instance of type variable.
swap(list);
}
但您可以添加从列表中获取的值,因为它们已知在列表的范围内:
private static <E> void swapHelper(List<E> list) {
list.add(list.get(0));
swap(list);
}
所以从swapHelper
调用原始swap
是安全的类型,因为你不能导致某些东西不能转换为E
(无论那种类型是什么)列表。
与tW
和tE
类似:
tW = tE
,则无法向tW
以外的null
添加任何内容,因此您无法将tE
置于包含任何内容的状态除了E
。tE = tW
,则可以将E
的非空实例添加到tE
。这可能意味着您可以将错误类的实例添加到tW
,这可能会导致运行时类型错误。因此,这项任务是被禁止的。请注意,分配列表不会导致列表被复制:如果您分配tE = tW
,然后tE == tW
,那么应用于tE
的所有更改也会通过{{tW
显示1}},因为它们是同一个实例。