泛型传参
1.有一个方法如下:
public void trans(List<Animal> animals) {
}
对trans
方法传参:
public void supply() {
List<Dog> list = new ArrayList<>();
trans(list);//报错
}
此处报错的原因,如果trans方法如下,则会出现运行时异常;因为此时animals指向的是Dog的list,实际上还是List,想要往里加Cat对象,报错:
public void trans(List<Animal> animals) {
animals.add(new Cat());
}
2.对trans方法修改:
public void trans(List<? extends Animal> animals) {
animals.add(new Dog());//报错
}
对trans
方法传参:
public void supply() {
List<Dog> list = new ArrayList<>();
trans(list);//编译通过
}
此时报错原因,因为trans方法可以接受Animal的子类List,所以传入List没有问题;但是trans方法中animals的类型未确认,trans方法只是声明可以接收Animal的子类List,但是只是某一个子类,并不能确认。所以在trans方法中,animals集合几乎只有读取功能,无法增加Animal或其子类形式的List。
如果trans的传参改一下,此时可以通过,:
public void trans(List<? super Animal> animals) {
animals.add(new Animal());//通过,因为animals可以接收Animal的超类,Animal超类的方法和字段一定少于子类。因为设计时,该方法内是以超类编写设计的(且是可以运行通过),其所调用的方法,Animal的子类一定也有这种方法,所以没问题。
animals.add(new Dog());//通过
}
public void supply() {
List<Animal> animals = new ArrayList<>();
List<Object> objects = new ArrayList<>();
trans(animals);//通过
trans(objects);//通过
}
但是此时trans方法内的animals,取值变得没有意义,因为你并不知道它到底是什么类型:
public void trans(List<? super Animal> animals) {
Object object = animals.get(0);
}
3.引用指向:
public void supply() {
List<Dog> list = new ArrayList<>();
List<Animal> animals = list;//报错
}
此时报错的原因,如果animals指向List,也就是说animals其实就是Dog类型的list,如果后续有animals.add(new Cat())将运行不通过(正常情况是可以的),如果改成下面的状况,一样报错:
public void supply() {
List<Animal> animals = new ArrayList<>();
List<Dog> list = animals;//报错
}
因为此时animals中可能包含Cat类型对象,list无法正确指向。