Вопрос
Мне трудно в этом разобраться.Допустим, у меня есть следующий код:
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;}
}
Как вы можете видеть, это позволяет перегружать возвращаемый тип методов при переопределении метода.