Как правильно вставить вложенные общие типы в 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>>