Please help me with this:
If Lion IS-A Animal and given Cage<T>:
Cage<? extends Animal> c = new Cage<Lion>(); // ok,
but
Set<Cage<? extends Animal>> cc = new HashSet<Cage<Lion>>(); // not ok
What I don't see here?
Please help me with this:
If Lion IS-A Animal and given Cage<T>:
Cage<? extends Animal> c = new Cage<Lion>(); // ok,
but
Set<Cage<? extends Animal>> cc = new HashSet<Cage<Lion>>(); // not ok
What I don't see here?
This is wrong because if it were allowed, then this would be legal:
Set<Cage<? extends Animal>> cc = new HashSet<Cage<Lion>>();
cc.add(new Cage<Tiger>()); // legal -- Cage<Tiger> is a Cage<? extends Animal>
Cage<Tiger> is within the bounds of the declaration, but not the definition, so this would crash.
You need:
Set<? extends List<? extends Number>> cc = new HashSet<ArrayList<Integer>>();
To explain why... I guess back up to a simpler version of your example:
Number a = new Integer(1); // OK
Set<Number> b = new HashSet<Integer>(); // not OK
this doesn't work because it would allow
b.add(new Double(3.0));
When assigning to a variable (Set<T>) with a non-wildcard generic type T, the object being assigned must have exactly T as its generic type (including all generic type parameters of T, wildcard and non-wildcard). In your case T is Cage<Lion>, which is not the same type as Cage<? extends Animal>.
What you can do, because Cage<Lion> is assignable to Cage<? extends Animal>, is use the wildcard type:
Set<? extends Cage<? extends Animal>> a = new Set<Cage<Lion>>();