Полагаю, вы хотели спросить, почему Animal animal=contraVarianceList.get(0);
не разрешено.
Думайте об этом так:
List<Animal> animals= new ArrayList<>();
List<Object> objects = new ArrayList<>();
List<? super Animal> contraVarianceList = animals;
List<? super Animal> contraVarianceList2 = objects;
animals.add(new Dog()); // Allowed
animals.add(new Tiger()); //Allowed
objects.add(new Dog()); // Allowed
objects.add(new Tiger()); //Allowed
//there is no type difference between contraVarianceList and contraVarianceList2
Animal animal = contraVarianceList.get(0); //compiler will complain
Animal animal2 = contraVarianceList2.get(0); //compiler will complain
Компилятор не может действительно знать, что любой из них несет только экземпляры Animal. Вы явно сказали ? super Animal
, так что это может быть также List, содержащий простой Object
.
Обычно вы используете эти типы списков для параметров методов, в которых вы ожидаете добавить элементов вместо чтения из списка. Итак, что-то вроде этого:
void populateAnimals(List<? super Animal> animals) {
//whatever code
animals.add(...);
}
Гарантирует, что вы можете использовать метод как с List<Object>
, так и с List<Animal>
.