Java中的Variance
Java中的Variance
默认情况下,Java中的Generics都是Invariant. 例如ArrayList
ArrayList<Number> x = new ArrayList<Integer>(); // 假如能编译通过
x.add(1);
x.add(3.5); // 错误!
int y = x.get(0); // 可以
这是因为,我们对一个Generic Collection的操作,往里面放东西和从里面往外拿东西所需要的类型是不一样的。假如Array<P>是Array
假如我们需要往里放东西,我们已知 Array<P>::add(P p), 根据替换原则 Array
假如我们要往外取东西, P p = Array<P>::get, 根据替换原则 Array
综合上面两条,对于一个Generic来说,假如Array<P>是Array
同时我们可以知道两点结论:
如果P是C的父类,假如这个Generic,我们只需要往外取东西(函数的返回值),那么Class<P> 就是 Class
如果P是C的父类,假如这个Generic,我们只需要往里放东西(函数的参数),那么Class
参考实例代码体会。在这里, List<? extends Number> 可以接受 List
public class Main {
private static List<Double> fList = Arrays.asList(1.0,2.0,3.0);
public static void main(String[] args) {
System.out.println(intSum(fList));
forEach(new Consumer<Number>() {
@Override
public void accept(Number number) {
System.out.println("number: " + number);
}
});
}
public static Number intSum(List<? extends Number> l) {
int sum = 0;
for (Number n : l) {
sum += n.intValue();
}
return sum;
}
public static void forEach(Consumer<? super Double> consumer) {
for (double x : fList)
consumer.accept(x);
}
}