Является ли List <?> Общим родителем List <Integer> и List <Number>?
Из этого учебника Oracle,
Хотя Integer
является подтипом Number
, List<Integer>
не является подтип List<Number>
и, фактически, эти два типа не связаны.
Общий родительский элемент List<Number>
и List<Integer>
равен List<?>
.
Мой вопрос касается второго предложения. Как мы можем сказать, что List<?>
является общим родителем List<Number>
и List<Integer>
?
?
обозначает неизвестный тип, который может быть любым ссылочным типом. Даже если я скажу, что ?
будет Object
здесь, Object
является общим родителем Integer
и Number
НЕ означает, что List<Object>
становится общим родителем List<Integer>
и List<Number>
.
Ответы
Ответ 1
Контекст, который вам нужно понять, не от Integer
или Number
, а от List
. Предположим, что вы были тем, кто создал класс List
, тогда как бы вы создали класс, чтобы он поддерживал только определенный тип класса.
Да, этот класс List
не будет использовать Object в качестве своего типа, а вместо этого использовать wild card ?
.
Как документация WildCards скажите
Итак, что такое супертип всех видов коллекций? Он написал Collection<?>
(произносится как "коллекция неизвестных" )
То же самое можно сказать о List.
Итак, что такое супертип всех видов списков? Он написал List<?>
(произносится как "Список неизвестных" )
Ответ 2
Мы можем доказать, что List<?>
является супертипом List<Number>
и List<Integer>
.
Из JLS 4.10.2 (выделено мной):
Учитывая объявление универсального типа C < F1,..., Fn > (n > 0), прямые супертипы параметризованного типа C<T1,...,Tn>
, где Ti (1 ≤ я ≤ n) является типом, являются следующими:
заменив C
на List
и n=1
, мы знаем, что List<?>
является прямым супертипом List<Number>
и List<Integer>
, если ?
содержит Number
и Integer
.
Мы можем доказать, что ?
содержит Number
и Integer
, потому что из JLS 4.5.1
Подстановочный знак ? extends Object
эквивалентен неограниченному шаблону ?
.
и далее:
Аргумент типа T1
называется содержит другой аргумент типа T2
, написанный T2
<= T1
, если набор типов, обозначаемый T2
, является предположительно подмножество множества типов, обозначаемое T1
при рефлексивном и транзитивном замыкании следующих правил (где <: обозначает подтипирование (§4.10)):
-
? extends T
<= ? extends S
, если T <: S - ...
-
T
<= ? extends T
мы можем использовать приведенные выше правила, чтобы доказать, что Number
<= ?
, поскольку Number
<= ? extends Number
<= ? extends Object
= ?
.
Ответ 3
В учебнике рассказывается о подстановочных знаках. Поэтому они хотят объяснить, когда и как вы должны их использовать. Когда вы читаете вперед, есть пример кода:
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number> numList = intList; // OK. List<? extends Integer> is a subtype of List<? extends Number>
Вы можете выполнить это назначение только в том случае, если ?
является общим родителем Integer
и Number
.
Я думаю, что в отношении с подстановочными знаками и дженериками можно сказать, что:
List<?>
является общим родителем List<Number>
и List<Integer>
потому что необходимо увидеть контекст учебника.
Ответ 4
Вот типы, которые имеют методы в Java с дженериками:
interface Collection<E> {
...
public boolean contains(Object o);
public boolean containsAll(Collection<?> c);
...
}
Первый метод вообще не использует generics! Второй метод - наш первый взгляд на
важная аббревиатура. Тип Collection означает:
Collection<? extends Object>
Расширение объекта является одним из наиболее распространенных видов использования подстановочных знаков, поэтому имеет смысл
предоставить короткую форму для ее написания.
Ответ 5
Вы смешиваете понятия наследования ООП или конкретные типы с одним из общих типов и отношений между этими генериками.
В одном из предложений в разделе "Подстановочные знаки и подтипы" говорится все:
Чтобы создать связь между этими классами... используйте верхний ограниченный шаблон
Для отношения типового типа ?
является просто самым верхним, ограниченным от возможных подстановочных знаков ? extends <type>
(верхний ограниченный шаблон), ? super <type>
(нижний ограниченный подстановочный знак) и фактический type
(точное совпадение или "верхний и нижний ограниченные подстановочные знаки" ).
Подстановочные знаки используются для того, чтобы обе концепции дженериков и ООП работали аккуратно друг с другом, но это не одно и то же. Проще говоря: List<?>
является общим родителем List<Integer>
и List<Number>
, потому что отношение подстановочных знаков указано как таковое, что любой другой подстановочный шаблон создает отношение подтипа с ?
.
Это более или менее неформальное объяснение, посмотрите на ответ dejvuth для конкретных частей спецификации.