Вопрос

Мне трудно в этом разобраться.Допустим, у меня есть следующий код:

class Animal { }
class Mammal extends Animal { }
class Giraffe extends Mammal { }
...
public static List<? extends Mammal> getMammals() { return ...; }
...

public static void main(String[] args) {
    List<Mammal> mammals = getMammals(); // compilation error
}

Почему присвоение приводит к ошибке компиляции?Ошибка выглядит примерно так:

Type mismatch: cannot convert from List<capture#4-of ? extends Mammal> to List<Mammal>

Согласно моему пониманию ковариации, getMammals() метод возвращает list это всегда будет содержать Mammal объекты, поэтому они должны быть присваиваемыми.Что я упускаю из виду?

Это было полезно?

Решение

Потому что getMammals мог бы вернуть List<Giraffe>, и если бы это можно было преобразовать в List<Mammal> тогда вы смогли бы добавить Zebra к этому.Вам не может быть разрешено добавлять Zebra к списку Giraffe, ты можешь?

class Zebra extends Mammal { }

List<Giraffe> giraffes = new List<Giraffe>();

List<Mammal> mammals = giraffes; // not allowed

mammals.add(new Zebra()); // would add a Zebra to a list of Giraffes

Другие советы

Ну, к сожалению, это так не работает.

Когда вы объявляете getMammals() для возврата List<? extends Mammal> это означает, что он может вернуться List<Mammal> или List<Giraffe> но не List<Animal>

Ваш main() должен выглядеть следующим образом:

public static void main(String[] args) {
    List<? extends Mammal> mammals = getMammals();
    Mammal mammal = mammals.get(0);
}

Редактировать:Что касается ковариации, то это то, что обычно подразумевается под этим:

class Animal {
    public Animal getAnimal() {return this;}
}

class Mammal extends Animal {
    public Mammal getAnimal() {return this;}
}

class Giraffe extends Mammal {
    public Giraffe getAnimal() {return this;}
}

Как вы можете видеть, это позволяет перегружать возвращаемый тип методов при переопределении метода.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top