Давайте посмотрим, что пойдет не так, если бы составили:
// Suppose list1, and list2 are initialized like this
List<? super Number> list1 = new ArrayList<Object>(); // valid assignment
List<? extends Integer> list2 = new ArrayList<Integer>(); // valid
// had this been valid, list1 and list2 both point to ArrayList<Integer>
list1 = list2;
// This is fine, as list1 declared type is `List<? super Number>`
list1.add(new Float(2.4f));
// The below code will compile fine, as list2.get(0) type is Integer.
// But it would throw ClassCastException at runtime.
Integer in = list2.get(0);
Таким образом, чтобы избежать его выполнения, компилятор выдаст ошибку во время компиляции.
Для первого случая, однако, вы каким-то образом изменили назначение, поэтому сравнение между двумя кодами не имеет смысла. Измените первый код на:
List<Number> list1 = null;
List<? super Integer> list2 = null;
list1 = list2;
И он тоже не сработает.
Кроме того, реверсирование задания во втором коде также скомпрометирует код.
Некоторые пояснения:
То, что вы должны помнить, есть ссылка супер класс может указывать на объект подкласса, но не наоборот. Если все списки, которые могут быть захвачены с помощью преобразования из list1
, также являются захваченными конвертируемыми из объявленного типа list2
, тогда назначение list2 = list1
было бы правильным, иначе оно не скомпилировалось.
Для первого кода:
List<? super Integer>
могут быть захвата преобразуются в следующие списки:
List<Integer>
List<Number>
List<Object>
List<Serializable>
Поскольку List<Number>
есть в списке, так что назначение list2 = list1
справедливо, как list1
может указывать только на List<Number>
. Но обратное присвоение list1 = list2
недействительно, так как List<Integer>
не является подтипом List<Number>
.
Аналогично, для 2-го кода:
Поскольку List<Integer>
не захват преобразуемых из List<? super Number>
, так list1 = list2
недействителен.
Кроме того, поскольку List<Object>
и все другие списки не являются отключаемыми с List<? extends Integer>
, поэтому list2 = list1
также недействителен.
Вы заметили, что ваши назначения в обоих кодах отменены. Измените первый код на 'list1 = list2', и он тоже не будет компилироваться. –