簡體   English   中英

在Java中將子類添加到通配符類型的泛型集合

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM