Java 中的数组是支持协变的,而范型不支持协变,先通过下面的代码了解什么是协变。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
    public static void main(String[] args) {
        // Number 数组可以指向 Integer 数组
        // 这就是数组的协变
        Number[] numbers = new Integer[5];
        numbers[0] = new Integer(1);
        // 而这句代码就会报错
        // 这是由于 Java 中的范型不支持协变导致的
        // 那 Java 中是怎么解决这个问题的呢?
        ArrayList<Number> numberList = new ArrayList<Integer>();
        // Java 通过 ? 来解决这个问题
        // 这样便不会报错了
        ArrayList<? extend Number> numberList = new ArrayList<Integer>();
    }

在下面这个场景的时候就能用到范型的协变。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Box {
    private static List<Object> list = new ArrayList<>();

    public static void main(String[] args) {
        ArrayList<Integer> numberList = new ArrayList<>();
        numberList.add(1);
        // 对于 addAll1 方法,就会报下面这个异常
        // java: incompatible types: java.util.ArrayList<java.lang.Integer> 
        // cannot be converted to java.util.List<java.lang.Object>
        addAll1(numberList);
        // 而通过使用协变,就能正常通过编译
        addAll2(numberList);
    }

    public static void addAll1(List<Object> src) {
        list.addAll(src);
    }

    public static void addAll2(List<?> src) {
        list.addAll(src);
    }
}