在Java中,泛型是不变的吗? [英] In Java Generics are invariant?
问题描述
编译以下代码失败:
public static void swap(List<?> list, int i, int j) {
list.set(i, list.set(j, list.get(i)));
}
喜欢:
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)));
但是,如果我这样做:
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)));
}
它运行良好.
但是我在这里有一个基本的疑问.据说泛型是不变的,所以List<String>
不是List<Object>
的子类型,对吧?
But I have a basic doubt here. Generics are said to be invariant, so List<String>
is not subtype of List<Object>
, right?
如果是这种情况,那么采用上述方法怎么能将List<?>
传递给List<E>
?如何运作?
If that is the case, then how come in the above method, we are able to pass List<?>
to List<E>
? How does this works?
推荐答案
答案是通配符.
List<?>
与List<Object>
不同
尽管java假定这两个都是Object的集合,但前者将匹配任何其他List<T>
的类型,而后者将不匹配除List<Object>
之外的任何List<T>
的类型.
List<?>
is not the same as List<Object>
while java assumes both are collections of Object, the former will match the type of any other List<T>
, while the latter will not match the type of any List<T>
besides List<Object>
.
示例:
public void doSomething(List<Object> list);
此函数仅接受List<Object>
作为其参数.但是:
This function will accept only List<Object>
as it's parameter. However this:
public void doSomething(List<?> list);
将接受任何List<T>
作为其参数.
will accept any List<T>
as it's parameter.
当与通用约束一起使用时,这可能非常有用. .例如,如果您想编写一个处理数字(Integer
s,Float
s等)的函数,则可以:
This can be extremely useful when used with generic constraints. For instance if you'd like to write a function that manipulates numbers (Integer
s, Float
s, etc.) you could:
public void doSomethingToNumbers(List<? extends Number> numbers) { ... }
这篇关于在Java中,泛型是不变的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!