Как правильно вставить вложенные общие типы в Java
В Java я могу использовать:
List<?> j = null;
List<Integer> j2 = (List<Integer>)j;
Итак, почему происходит следующее:
List<List<?>> i = null;
List<List<Integer>> i2 = (List<List<Integer>>)i;
Ответы
Ответ 1
В вашем 1 st фрагменте:
List<?> j = null;
List<Integer> j2 = (List<Integer>)j;
Компилятор не даст вам ошибку, потому что List<?>
является супер-типом List<Integer>
, потому что семейство типов, обозначенное подстановочным знаком "?"
, является надмножеством Integer
. Таким образом, вы можете выполнить трансляцию с List<?>
до List<Integer>
(как вы можете сказать, вниз), но компилятор покажет вам Unchecked Warning, чтобы спасти вас от приведения от say - List<Date>
до List<Integer>
. Предупреждение отображается, потому что в противном случае выполнение будет выполнено во время выполнения из-за стирания типа.
В случае 2 nd:
List<List<?>> i = null;
List<List<Integer>> i2 = (List<List<Integer>>)i;
Здесь вы отправляете из List<List<?>>
(от FIRST отсюда) до List<List<Integer>>
(упомянутый SECOND отсюда).
Так как FIRST не является супертипом SECOND, очевидно, потому что семейство типов, обозначаемое List<?>
(оно может быть List<Long>
, List<Date>
, List<String>
или что-то еще) не является супер-набором List<Integer>
. Следовательно, ошибка компилятора.
Рекомендуемое чтение:
Ответ 2
Try:
List<? extends List<?>> i = null;
List<List<Integer>> i2 = (List<List<Integer>>)i;
Источник (этот источник будет ссылаться на другие отличные источники):
fooobar.com/questions/378579/...
Ответ 3
Я предполагаю, что вам нужно сделать подстановочный знак, чтобы отдать его тому, что вы хотите.
List<?> j = null;
List<Integer> j2 = (List<Integer>)j;
List<List<?>> i = null;
List<List<Integer>> i2 = (List<List<Integer>>) (List<?>) i;
Это компилируется отлично. Вам просто нужно было сделать дополнительный бросок, чтобы добавить небольшой буфер.
Смотрите здесь: http://ideone.com/xh88lX
Если вы хотите знать, почему, здесь
В принципе, здесь соответствующая информация
Вот еще один способ взглянуть на это:
- Генераторы Java являются инвариантными по типу
- Есть преобразование из целого в число, но
List<Integer>
не является List<Number>
- Аналогично, a
List<Integer>
может быть преобразован захватом с помощью List<?>
, но a List<List<Integer>>
не является List<List<?>>
- Используя ограниченный подстановочный знак, a
List<? extends Number>
может захватить-преобразовать a List<Integer>
- Аналогично,
List<? extends List<?>>
может захватывать-преобразовывать a List<List<Integer>>