将父对象添加到List <! - ?扩展Parent - > - Java

时间:2013-12-05 04:14:49

标签: java generic-collections

我正在尝试将子类对象放入List中,但由于作为注释提到的编译器错误,我无法这样做。有人可以指出在Java中执行此操作的正确方法是什么?

public class Animal { }

class Util {

    private Map<Class<? extends Animal>, List<? extends Animal>> animalListMap;

    public void registerAnimal(Class<? extends Animal> animalClass, Animal animalObject) {

        if (animalListMap.containsKey(animalClass)) {
            //Append to the existing List
            List<? extends Animal> animalList = animalListMap.get(animalObject);
            animalList.add(animalObject); //COMPILE ERROR- The method add(capture#3-of ? extends Animal) in the type List<capture#3-of ? extends Animal> is not applicable for the arguments (Animal)
        } else {
            // and the new entry
            List<Animal> vos = new ArrayList<Animal>();
            vos.add(animalObject);
            animalListMap.put(animalClass, vos);
        }
    }
}

4 个答案:

答案 0 :(得分:3)

您无法向List<? extends Animal>添加任何内容。 List<? extends Animal>表示“我不知道什么,但是某些东西 - 扩展动物”的列表,可以是List<Animal>List<Cat>

如果可以的话,这段代码会编译:


List dogs = new ArrayList();
List animals = dogs;
animals.add(new Cat());
Dog dog = dogs.get(0);

但是,您可以将List<? extends Animal>更改为List<Animal>,这似乎是您想要的。

答案 1 :(得分:1)

你宣布

List<? extends Animal> animalList = animalListMap.get(animalObject);

? extends Animal是由Animal类限定的通配符。因此,animalListMap.get(animalObject);可以返回List<Donkey>List<Mouse>List<Pikachu>,假设DonkeyMousePikachu都是子类Animal。但是,使用通配符时,只要它是Animal的子类型,您就告诉编译器您不关心实际类型是什么。

由于你不知道它是什么,你实际上不能添加任何东西(null除外)。如果你得到的是List<Pikachu>,但animalObject实际上引用了Donkey对象,那么你就会遇到问题。这就是编译器不会让这段代码编译的原因。

如果您有List<Animal>,则可以添加具有类型或父类型Animal的任何对象。

答案 2 :(得分:0)

因为animalList是一个扩展动物的东西的列表,但可能不是具体的动物。换句话说,它可能仅限于动物的某些亚型,例如你可能有狮子,老虎或熊的名单(哦,我的!)。

同样,您的代码很容易出现怪异,请考虑以下调用代码示例:

myUtil.registerAnimal(Zebra.class, new Tiger());

答案 3 :(得分:0)

您必须更改此声明

private Map<Class<? extends Animal>, List<? extends Animal>> animalListMap;

如果您打算将动物添加到列表中。

List<? extends Animal>>指示编译器不允许向该列表添加除null之外的任何内容。