蔡香满屋
站在牛顿头上吃苹果

  之所以需要泛型通配符,具体原因首先让我们看下,首先定义一个父类Animal如:

public class Animal {
	private String type;
	
	public Animal(String type) {
		this.type = type;
	}
	
	public void show() {
		System.out.println("type = " + type);
	}
}

  定义一个子类Cat:

public class Cat extends Animal{
	public Cat(String type) {
		super(type);
	}
}

  定义一个字类Dog:

public class Dog extends Animal{
	public Dog(String type) {
		super(type);
	}
}

  编写测试类就会发现一个问题,但是只是使用泛型类的情况,代码跟报错信息如:

package com.test.cgb;

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

public class GenericDemo {
	public static void main(String[] args) {
		List<Animal> animals = new ArrayList<>();
		animals.add(new Animal("动物"));
		List<Cat> cats = new ArrayList<>();
		cats.add(new Cat("布偶猫"));
		cats.add(new Cat("英杰猫"));
		List<Dog> dogs = new ArrayList<>();
		dogs.add(new Dog("金毛"));
		dogs.add(new Dog("拉布拉多"));
		/**
		 * 下面之所以报错是因为:
		 * 泛型子类型
		 * A--一个类或者一个接口
		 * B--A的字类或者子接口
		 * G--泛型类或者泛型接口
		 * G<B>不是G<A>的子类型,其实二者没有任何关系。所以比如List<Animal>的字类不是List<Cat>
		 */
		GenericDemo.showAnimalUserGeneric(animals);
		/**
		 * 执行这两个方法GenericDemo.showAnimalUserGeneric(cats); 
		GenericDemo.showAnimalUserGeneric(dogs);就会报错
		 *  报错信息为:The method showAnimalUserGeneric(List<Animal>) in the type GenericDemo is not applicable 
		 *  for the arguments (List<Cat>)
		 */
		GenericDemo.showAnimalUserGeneric(cats); 
		GenericDemo.showAnimalUserGeneric(dogs);
}
	// 使用泛型的情况
			public static void showAnimalUserGeneric(List<Animal> list) {
				for (int index = 0; index < list.size(); index ++) {
					Animal animal = (Animal) list.get(index);
					animal.show();
				}
			}
}

  

于是需要使用通配符来解决这个问题:

类型通配符,用来匹配类型实参如使用List<?>匹配List<Animal>,也就是在编译时获取到Object类型:

 

 但是单独List<?>还有个缺点就是无法对传入的参数类型进行限制,因为这个showAnimalUserGeneric(List<?> list)方法是可以接收字符串的,这个在编译器是不会报错的,但是在运行期Animal animal = (Animal)list.get(index)时String就会无法转换成Object类型,就会报错的。所以需要使用List<? extends Animal>,这样可以限制参数类型例如没有使用List<? extends Animal>之前是这样的:

 

 泛型通配符上线:接着就是使用了List<? extends Animal>

语法<? extends 类或接口(1个)>表示?能匹配的类型要么是指定的类或接口,要么是其子类或子接口:

 

 泛型通配符下线:

语法List<? super 类或接口(1个)>表示?能匹配的类型要么是指定的类或接口,要么是其父类或父接口:

 

posted on 2020-03-01 18:43  蔡香满屋  阅读(179)  评论(0)    收藏  举报