List<B> list;
Здесь объявляется переменная, представляющая собой список, с гарантией того, что все в этом списке может быть приведено B
(то есть B
, подкласс B
или null), to which you can only add things which can be cast to
B`.
private void checkWithoutInheritance(final Collection<A> s) {
Здесь объявляется метод, принимающий параметр, который является коллекцией, с гарантией того, что все в этой коллекции может быть приведено к A
, к которому можно добавлять только вещи, которые можно привести к A
.
Это означает, что checkWithoutInheritance
может сделать это:
s.add(new A());
Если бы вы могли позвонить
checkWithoutInheritance(list);
тогда list
теперь будет содержать экземпляр A
, который нельзя преобразовать в B
, что нарушает гарантию на содержимое list
.
Как таковой, он запрещен компилятором. Компилятору не важно, что вы не добавите A
к s
, потому что вы могли бы . Ошибка на стороне безопасности.
С другой стороны:
private void checkWithInheritance(final Collection<? extends A> s) {
Здесь объявляется метод, принимающий параметр, который является коллекцией, с гарантией того, что все в этой коллекции является чем-то, что можно преобразовать в некоторый подкласс A
.
Вы не можете добавить A
к нему, потому что вы не знаете, означает ли «некоторый подкласс» A
, B
или что-то еще полностью.
Таким образом, вы не можете написать s.add(new A());
в его теле метода, поэтому безопасно передать ему List<B>
.