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