С List<Animal>
вы знаете, что у вас определенно есть список животных. Необязательно, чтобы все они были в точности «Animal's» - они также могут быть производными типами. Например, если у вас есть Список животных, имеет смысл, что пара может быть козами, а некоторые из них - кошками и т. Д. - верно?
Например, это полностью верно:
List<Animal> aL= new List<Animal>();
aL.add(new Goat());
aL.add(new Cat());
Animal a = aL.peek();
a.walk(); // assuming walk is a method within Animal
Конечно, следующее недействительно:
aL.peek().meow(); // we can't do this, as it's not guaranteed that aL.peek() will be a Cat
С List<? extends Animal>
вы делаете заявление о типе списка, с которым имеете дело.
Например:
List<? extends Animal> L;
На самом деле это не объявление типа объекта, который L может удерживать. Это утверждение о том, на какие списки может ссылаться L.
Например, мы могли бы сделать это:
L = aL; // remember aL is a List of Animals
Но теперь все, что компилятор знает о L, это то, что это Список [либо Animal, либо подтипа Animal]
Итак, теперь неверно следующее:
L.add(new Animal()); // throws a compiletime error
Потому что, насколько нам известно, L может ссылаться на список Коз, к которому мы не можем добавить Животное.
Вот почему:
List<Goat> gL = new List<Goat>(); // fine
gL.add(new Goat()); // fine
gL.add(new Animal()); // compiletime error
Выше мы пытаемся преобразовать животное в козу. Это не работает, потому что что, если после этого мы попытаемся заставить это Животное «бить головой», как это сделал бы козел? Мы не обязательно знаем, что Животное может это делать.
person
Cam
schedule
04.04.2010
<T extendsAnimal> void foo(List<T> param)
? - person Alex78191   schedule 07.10.2019