Чтобы понять, почему не имеет смысла создавать экземпляр new ArrayList<? extends A>()
, на самом деле мы можем эквивалентно создать new ArrayList<B>()
с любым произвольным классом или интерфейсом B
(даже с тем, который не связан ни с одним из ваших объектов ), который реализует A
, и созданный в результате ArrayList может быть безопасно назначен переменной типа ArrayList<? extends A>
. Тогда вы можете задаться вопросом, о, это глупо, потому что объекты, которые я хочу поместить в него, не относятся к классу B, так как это может быть одинаковым? Но - это то же самое, потому что вы все равно не можете поместить что-либо в ссылку типа Something<? extends A>
. Вот почему не имеет смысла создавать new ArrayList<? extends A>()
.
Как я могу указать, что я хочу любой объект, который реализует A
Интерфейс, который будет разрешен внутри Списка безопасным для типов способом? я
хочу иметь возможность вызывать данный метод A над всеми объектами,
относительно того, к какому типу класса они относятся.
Это именно то, что ArrayList<A>
. Он допускает все экземпляры A
(конечно, все объекты, которые реализуют A
, являются экземплярами A
), и вы можете использовать любые методы A
для них. Что-то вроде этого - то, что вы хотите:
List<A> myList = new ArrayList<A>();
Нечто подобное List<? extends A>
используется только в тех случаях, когда вы получаете объект List из какого-то другого кода, и вы не знаете (или не заботитесь), каков именно общий параметр, с которым они его создали. (В таком случае вы не можете помещать объекты в список.) Это полностью отличается от вашего случая, когда вы создаете объект списка, поэтому вы решаете и, следовательно, точно знаете, какой универсальный параметр используется.