[英]Add subclass to wildcard-typed generic collection in java
这是合法的:
List<? extends Animal> animals = getMonkeys();
...
List<Monkey> getMonkeys(){
...
}
以下导致编译器错误:
animals.add(new Donkey());
为什么? 如何合法添加子类型?
编译器不知道通配符可能是哪个子类。 据了解,它可能是List<Fish>
。 为了保持类型安全,编译器必须阻止调用add
,因为不应允许将Monkey
添加到可能为List<Fish>
。
List<? extends Animal> animals = new ArrayList<Fish>(); // legal
animals.add(new Monkey()); // unsafe; compiler error
animals.add(new Donkey()); // also unsafe; compiler error
为防止这种情况,您需要消除变量中的通配符,以便编译器知道通用类型参数。 List<Animal>
或List<Monkey>
(或List<Donkey>
视情况而定))将允许您使用非null
的参数调用add
。 如果必须调用getMonkeys()
,则必须使用其返回类型List<Monkey>
。
List<Monkey> monkeys = getMonkeys();
monkeys.add(new Monkey());
只需将列表声明为List<Animal>
。 任何来自Animal
类扩展的对象都可以插入到那里。
在List<? extends Foo>
使用通配符List<? extends Foo>
当您遍历集合的元素并且希望/需要集合中的元素属于特定类时, List<? extends Foo>
。 例如:
class Animal {
public String getSpecie() {
return "generic animal";
}
}
class Donkey extends Animal {
@Override
public String getSpecie() {
return "generic donkey";
}
}
class Mokney extends Animal {
@Override
public String getSpecie() {
return "generic monkey";
}
}
//some method in an utility class...
//we are declaring that only List<Animal> or List<some class that extends animal> can be passed as argument
public void printSpecies(List<? extends Animal> animalList) {
//we can be sure every element in animalList is an animal always
for (Animal animal : animalList) {
System.out.println(animal.getSpecie());
}
}
//calling the method above...
List<Monkey> monkeyList = ...
printSpecies(monkeyList); //compiles and works
List<Donkey> donkeyList = ...
printSpecies(donkeyList); //compiles and works
List<String> stringList = ...
printSpecies(stringList); //doesn't compile
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.