为什么不能 List<? extends Animal> 被替换为 List<Animal>?

yas*_*eco 5 java oop generics covariance contravariance

考虑以下代码:

public class Main {

    static class Animal {}

    static class Dog extends Animal {}

    static List<? extends Animal> foo() {
        List<Dog> dogs = new ArrayList<>();
        return dogs;
    }

    public static void main(String[] args) {
        List<Animal> dogs = Main.foo(); // compile error
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图理解为什么它不能编译。意思是,为什么编译器不让我将其List<? extends Animal>称为 a List<Animal>?这与类型擦除机制有关吗?

And*_*ner 10

AList<Animal>List您可以添加任何 Animal(或空值)的 a ,您从中取出的所有内容都将是Animal.

一个List<? extends Animal>是只包含一个列表一个特定的子类Animal(或空),而你不知道哪一个; 这允许您将从中取出的所有内容视为Animal,但不允许向其中添加任何内容(文字除外null)。


AList<? extends Animal>不能充当 a List<Animal>,因为这将允许您执行以下操作:

List<Cat> listOfCats = new ArrayList<>();
List<? extends Animal> listOfSomeAnimals = listOfCats;  // Fine.
List<Animal> listOfAnimals = listOfSomeAnimals;  // Error, pretend it works.
listOfAnimals.add(new Dog());
Run Code Online (Sandbox Code Playgroud)

现在,因为listOfCatslistOfSomeAnimalslistOfAnimals都是相同的列表,Dog已添加到listOfCats。像这样:

Cat cat = listOfCats.get(0);  // ClassCastException.
Run Code Online (Sandbox Code Playgroud)

  • 实际上你不能向 `List&lt;? 添加任何内容。扩展 Animal&gt;` 除了 null 之外。 (2认同)