在Java中,泛型是不变的?

bat*_*man 1 java generics

编译以下代码失败:

public static void swap(List<?> list, int i, int j) {
       list.set(i, list.set(j, list.get(i)));
}
Run Code Online (Sandbox Code Playgroud)

喜欢:

Swap.java:5: set(int,capture#282 of ?) in List<capture#282 of ?> cannot be applied to (int,Object)
           list.set(i, list.set(j, list.get(i)));
Run Code Online (Sandbox Code Playgroud)

但如果我这样做:

public static void swap(List<?> list, int i, int j) {
       swapHelper(list, i, j);
}

private static <E> void swapHelper(List<E> list, int i, int j) { list.set(i, list.set(j, list.get(i)));
}
Run Code Online (Sandbox Code Playgroud)

它的工作完美.

但我在这里有一个基本的疑问.仿制药据说是不变的,所以List<String>不是亚型List<Object>,对吧?

如果是这样,那么如何在上面的方法中,我们能够传递List<?>给List<E>?这是怎么回事?

Ass*_*saf 8

答案是通配符.

List<?>是不一样的List<Object> ,而Java假定都是对象的集合,前者将匹配任何其他的类型List<T>,而后者将不匹配的任何类型List<T>之外List<Object>.

例:

public void doSomething(List<Object> list);
Run Code Online (Sandbox Code Playgroud)

此函数仅接受List<Object>其参数.不过这个:

public void doSomething(List<?> list);
Run Code Online (Sandbox Code Playgroud)

将接受任何List<T>作为它的参数.

当与通用约束一起使用时,这非常有用.例如,如果您想编写一个操作数字(Integers,Floats等)的函数,您可以:

public void doSomethingToNumbers(List<? extends Number> numbers) { ... }
Run Code Online (Sandbox Code Playgroud)