public void addAllAnimals(ArrayList<? extends Animal> animalLikeList){
// I need to add animal objects (eg Dog, Cat that extends Animal) to animalLikeList.
}
我知道它不允许直接添加,因为? extends Animal
代表Animal
的未知子类型。
我的问题是:add
或addAll
Animal
或Animal
对象的子类型是否有任何方式(间接方式)到animalLikeList
?
答案 0 :(得分:8)
不,没有直接合法的方式(除了不安全的类型演员)。您只能将元素添加到使用super
声明的通用集合,而不是extends
。这可能更容易记住,首字母缩略词 PECS (制作人 - 扩展,消费者 - 超级),由Josh Bloch在 Effective Java,2nd Edition ,第28项中推广。
事实上,你似乎追求的似乎没有直接意义。 List<? extends Animal>
可以是例如一个List<Dog>
或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());
请注意,此方法是通用的,带有命名类型参数,可确保列表的实际泛型类型与要添加到其中的元素类型相同。
您可以使用E
简单地替换Collection<E>
参数,以便一次添加多个对象。
答案 1 :(得分:4)
我的问题是:是否有任何方式(间接方式)向AnimalLikeList添加或添加动物对象的Animal或子类型?
不是没有改变签名,而且有充分的理由。假设您要将Dog
值添加到该列表中......但假设它在逻辑上是猫的列表:
ArrayList<Cat> cats = new ArrayList<Cat>();
addAllAnimals(cats);
您应该无法向Dog
添加ArrayList<Cat>
吗?
如果您希望能够将任何类型的动物添加到列表中,您需要:
public void addAllAnimals(ArrayList<Animal> animalLikeList) {
或
public void addAllAnimals(ArrayList<? super Animal> animalLikeList) {
答案 2 :(得分:1)
为什么不直接更改方法签名以使用不变的类型参数?
public void addAllAnimals(ArrayList<Animal> animalLikeList){
animalLinkedList.add(new Dog());
animalLinkedList.add(new Cat());
}
它应该可以正常工作,并且通过使用不变类型参数,您将被允许从列表中读取或写入其中,并且通过子类型pollymorphism的规则,它可以包含您想要的任何种类的动物。
不要试图通过狗列表或猫列表,而是将动物列表传递给方法。
答案 3 :(得分:0)
ArraList<anything extends animal> list= new ArrayList<anything extends animal>();
addAllAnimals(list);
这完全有效。您的方法addAllAnimals
将接受声明包含任何子类型Animal的任何arrayList。
并且为了添加一个对象/ List,你可以在任何对象/列表中找到Animal的哪个子类型。
答案 4 :(得分:0)
不是以类型安全的方式......
一个想法是将签名更改为:
public static <T extends Animal> void addAllAnimals(ArrayList<? super T> list){}
您可以将T或T的子类型添加到T ...
列表中答案 5 :(得分:0)
您可以在通用集合中使用非通用方法addAll
public void testExtends(ArrayList<? extends Parent> list) throws Exception {
/* list.add(new Child());
list.add(new Parent());
list.add(new GrandParent());
// can not add
*/
/**
* Unsafe collection way
*/
ArrayList list2=new ArrayList();
list.addAll(list2);
}