泛型通配符

上一节讲到,泛型是不变的,可有时候需要实现协变,在两个类型之间建立某种类型的向上转型关系,应该使用通配符.

概览

泛型通配符有三种:

  • ? 任意类型,如果没有明确,那么就是Object以及任意的java类
  • ? extends E 向下限定,E及其子类
  • ? super E 向上限定,E及其父类

? 通配符

首先定义两个类

class Person{
    public void say(){
        System.out.println("person say hi!!");
    }
}
class Student extends Person{
    @Override
    public void say() {
        System.out.println("student say hi!!");
    }
}
    @Test
    public void testArrayList(){
        ArrayList<?> list = new ArrayList<>();
        list.add("helo");
    }

上面的代码,看上去就是对"?"通配符的使用,而且看起来并没有任何逻辑问题,定义一个任意类型的泛型,然后添加String类型的值,但是list.add("helo");会报错,list不能添加数据,因为"?"通配符不是这么使用的.

泛型通配符不是用在定义对象上,而是用在方法形参上.

 @Test
    public void testArrayList(){
        ArrayList<Student> list = new ArrayList<>();
        list.add(new Student());
        method(list);  //可以传入Student的类型

        ArrayList<Person> list2 = new ArrayList<>();
        list2.add(new Person());
        method(list2);  //可以传入Person的类型
        
    }

    public static void method(ArrayList<?> list){    //定义泛型通配符 ,这个方法可以传入任意类型的泛型.
        for (Object o : list) {
            System.out.println(o);
        }
    }

? extends E

? extends E 是上界限定,限定了天花板,只能是E及其子类

    @Test
    public void testExtendArray(){
        ArrayList<Person> list1 = new ArrayList<>();
        list1.add(new Person());
        method2(list1);  //method2中传入Person类的实例,没有问题
        ArrayList<Student> list2 = new ArrayList<>();
        list2.add(new Student());
        method2(list2);  //method2中传入Student类的实例,也没有问题,因为Student继承Person
        ArrayList<Object> list3 = new ArrayList<>();
        list3.add("");
        method2(list3); //这里就会出错,因为Object不是Person的子类,所以不能这样使用. //error
    }
    public static void method2(ArrayList<? extends Person> list){  //这里就是接受Person及其person子类对象的list
        for (Person person : list) {
            System.out.println(person);
        }
    }

? super E

? super E 是下界限定,限定为E及其父类

@Test
    public void testSuperArrayList(){
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person());
        method3(list);  //传入Person类型的ArrayList 没有问题
        ArrayList<Object> list2 = new ArrayList<>();
        list2.add("");
        method3(list2);  //传入Object类型也没有问题,因为Object是Person的父类
        ArrayList<Student> list3 = new ArrayList<>();
        list3.add(new Student());
        method3(list3); // error 在这里就会出错,是因为Student不是Person的父类
    }
    public static void method3(ArrayList<? super Person> list){  //这里限定为Person及其父类
        for (Object o : list) {
            System.out.println(o);
        }
    }
原文地址:https://www.cnblogs.com/liuzhidao/p/13745296.html