将对象添加到"?extends"类型的通用集合中

nam*_*olk 7 java generics collections

public void addAllAnimals(ArrayList<? extends Animal> animalLikeList){

 // I need to add animal objects (eg Dog, Cat that extends Animal) to animalLikeList.

}
Run Code Online (Sandbox Code Playgroud)

我知道它不允许直接添加,因为? extends Animal代表未知的子类型Animal.

我的问题是:是不是有什么办法(间接的方式),以addaddAll一个Animal或亚型Animal对象的animalLikeList

Pét*_*rök 8

不,没有直接合法的方式(除了不安全的类型演员).您只能将元素添加到声明的泛型集合中super,而不是extends.这可能更容易记住,首字母缩略词PECS(Producer - Extends,Consumer - Super),由Josh Bloch在Effective Java,第2版,第28项中推广.

事实上,你似乎追求的似乎没有直接意义.A List<? extends Animal>可以是例如a List<Dog>或a List<Cat>.前者只能接受Dog元素,后者只能接受Cat.由于您无法在Java中实例化通用(不可恢复)类型,因此您必须在运行时知道您正在处理狗列表,因此您只尝试向其添加狗(反之亦然).这意味着您无法在本地和静态地创建要添加的对象 - 您必须以通用方式获取它们,而且还允许编译器确保每次都匹配具体类型.最简单的方法是将元素作为通用参数传递.所以这样做是可行和安全的:

public <E extends Animal> void addAllAnimals(List<E> animalLikeList, E animal) {
    animalLikeList.add(animal);
}

List<Dog> dogs = new ArrayList<Dog>();
List<Cat> cats = new ArrayList<Cat>();

addAllAnimals(dogs, new Dog());
addAllAnimals(cats, new Cat());
Run Code Online (Sandbox Code Playgroud)

请注意,此方法是通用的,具有命名类型参数,可确保列表的实际泛型类型与要添加到其中的元素类型相同.

您可以简单地E用a 替换参数以一次Collection<E>添加多个对象.