Помогите мне с этим:
Если Lion IS-A Animal
и данный Cage<T>
:
Cage<? extends Animal> c = new Cage<Lion>(); // ok,
но
Set<Cage<? extends Animal>> cc = new HashSet<Cage<Lion>>(); // not ok
Что я не вижу здесь?
При присвоении переменной ( Set
) универсального типа без подстановочных знаков T
назначаемый объект должен иметь точно T
как его общий тип (включая все параметры универсального типа T
, подстановочные знаки и без подстановочных знаков). В вашем случае T
- это Cage
, что отличается от типа Cage расширяет Animal>
.
Что вы можете сделать, потому что Кейдж <Лев>
может быть назначен на Кейдж extends Animal>
, используется тип подстановочного знака:
Set<? extends Cage<? extends Animal>> a = new Set<Cage<Lion>>();
Вам нужно:
Set<? extends List<? extends Number>> cc = new HashSet<ArrayList<Integer>>();
Чтобы объяснить, почему ... Я думаю, вернемся к более простой версии вашего примера:
Number a = new Integer(1); // OK
Set<Number> b = new HashSet<Integer>(); // not OK
это не работает, потому что это позволит
b.add(new Double(3.0));
Это неверно, потому что, если бы это было разрешено, то это было бы законно:
Set<Cage<? extends Animal>> cc = new HashSet<Cage<Lion>>();
cc.add(new Cage<Tiger>()); // legal -- Cage<Tiger> is a Cage<? extends Animal>
Cage
находится в границах объявления, но не определения, поэтому это рухнет.