Для примера такой код:
public void add(List<? super Number> list) {
list.add(1D); // можно
list.add(new Object()); // нельзя
}
Почему так? Ведь здесь - <? super Number>
- написано: "любой тип, являющийся супер-классом для Number
". А работает всё наоборот: "любой тип - наследник Number
". Что не так? Почему работает наоборот?
Да, <? super Number>
действительно подразумевает "любой тип, являющийся супер-классом для Number
". Плюс сам Number
.
По этой причине вы можете передать в метод, например, List<Object>
.
Так как тип элементов в этом списке "что-то, являющееся суперклассом для Number
", то можно добавлять в список элементы, тип которых является дочерним для Number
. Например, Integer
:
public void add(List<? super Number> list)
{
list.add(1);
}
Это позволительно, так как в список можно добавлять элементы, тип которых является дочерним для типа элементов списка. Как в случае с обычным List<Number>
:
List<Number> list = new ArrayList<>();
list.add(1);
Однако вы не можете добавить в список new Object()
, потому что нет никаких гарантий того, что в списке можно хранить элементы типа Object
: под ?
может "скрываться" не только Object
, но и, например, сам Number
. В случае других классов (? super X
), имеющих промежуточные классы между Object
и самим X
- ещё и любой промежуточный класс.
Так как истинный тип элементов списка неизвестен (?
), но любой класс имеет в качестве суперкласса Object
, то с полученным из списка элементом можно работать только как с Object
. Даже с той единицей, которую только что туда сами и положили.
В случае <? extends Number>
подразумевается "любой тип, являющийся дочерним классом для Number
". Плюс сам Number
.
В этом случае вы сможете передать в метод, например, List<integer>
.
Так как тип элементов "что-то, являющееся дочерним классом для Number
", то вы ничего не сможете добавить в список (кроме, разве что, null
), ибо неизвестно что именно там может храниться.
А вот с полученным из списка элементом вы сможете работать как с Number
:
public static void add2(List<? extends Number> list)
{
int value = list.get(0).intValue();
}
Потому что какие бы там ни были элементы в списке, но они определённо из дочерних для Number
классов, а, значит, могут работать как Number
.
Все очень просто.
Определение List
'a с wildcard
вида <? super Number>
обозначает, что в списке хранятся элементы какого то типа от которого наследуется Number
. Здесь не обязательно должен быть Object
, там может быть и какой то промежуточный класс в иерархии наследования.
Например.
Есть классы A,B,C
. A
наследуется от B
, B
в свою очередь наследуется от C
.
Если мы пишем List<? super A>
, это значит что список может быть как List<A>
,List<B>
или List<C>
. Соответственно, если придет List<B>
то положить туда элементы типа C
, будет ошибкой. От этой ошибки компилятор вас и предупреждает.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
В каком виде приходит ответ от facebook, после отправки запроса
Имеется файл txt с содержимым, как сделать так что бы содержимое этого файла отображалось в таблице (tableView)?
Почему-то не грузятся css в Open Server на втором компьютере, а на основном всё замечательно работает ! Не могу понять в чём проблема
Здравствуйте! Подскажите пожалуйста, как верно оформить анкорную ссылку в шаблоне компонента Битрикса? Есть шаблон компонента и необходимо...