首页 > 解决方案 > add() 操作在“?extends”和“?super”的区别

问题描述

package test16;

import java.util.ArrayList;
import java.util.List;

class A {
}

class B extends A {
}

public class Test1 {
    public static void main(String[] args) {
        List list1 = new ArrayList();
        List<A> list2 = new ArrayList<A>();
        List<A> list3 = new ArrayList<>();
        List<A> list4 = new ArrayList<B>();

        List<? extends A> list101 = new ArrayList<A>();
        List<? extends A> list102 = new ArrayList<B>();

        List<? extends A> list5 = new ArrayList<>();
        A getA = list5.get(0);// return A
        list5.add(new A());// error
        list5.add(new B());// error
    }
}

? 扩展:所有 add() 错误。

package test17;

import java.util.ArrayList;
import java.util.List;

class A {
}

class B extends A {
}

public class Test1 {
    public static void main(String[] args) {
        List list1 = new ArrayList();
        List<B> list2 = new ArrayList<B>();
        List<B> list3 = new ArrayList<>();
        List<B> list4 = new ArrayList<A>();

        List<? super B> list101 = new ArrayList<A>();
        List<? super B> list102 = new ArrayList<B>();

        List<? super B> list5 = new ArrayList<>();
        Object object = list5.get(0);//return Object
        list5.add(new A());// error
        list5.add(new B());// ok
    }
}

? super : add() 运行正常。


想知道泛型设计师是什么考虑,extends根本不能加,super可以加

但stackoverflow找不到答案。

非常感谢!

标签: javagenerics

解决方案


Java 泛型中的扩展通配符。

private static double sum(Collection<? extends Number> numbers) {
double result = 0.0;

for (Number num : numbers) result += num.doubleValue();

return result;
}

上面的方法有通配符有<? extends Number>. 编译器将允许传递Number. 但是,您不能将元素添加到使用 extends 通配符声明的集合中。

List<? extends Number> numbers = new ArrayList<Integer>();
numbers.add(123); // COMPILE ERROR 

否则,我们可以向一个只接受整数的集合添加一个双精度数。

Java 泛型中的超级通配符。

public static void append(Collection<? super Integer> integers, int n) {
for (int i = 1; i <= n; i++) {
    integers.add(i);
}
}

在上述方法中,您可以限制方法中添加的元素为 Integer 类型,而我们也希望接受 Integer 超类型的集合,因为将整数添加到数字集合中是完全合法的。

List<Number> numbers = new ArrayList<Number>();
append(numbers, 5);
numbers.add(6.789);

System.out.println(numbers);

超级通配符背后的思想:(用通配符声明的类型<? super T>

  1. 它可以接受任何 T 的超类型
  2. 我们可以将元素添加到集合中。但是类型仅限于 T
  3. 它不能传递给具有使用扩展通配符声明的参数的方法。

具有扩展和超级的泛型


推荐阅读