I've heavily simplified my problem. Here's how it reads.
I'm trying to figure out why the following code does not compile:
List<AnonType<AnonType<?>>> l = new ArrayList<AnonType<AnonType<?>>>();
l.add( new AnonType<AnonType<String>>() );
where
public class AnonType<T> {
T a;
List<T> b;
}
The compiler error is saying that add is not applicable for the argument given. OTOH, the following code with only 1-level nested wildcard compiles perfectly:
List<AnonType<?>> l = new ArrayList<AnonType<?>>();
l.add( new AnonType<String>() );
The following compiles as expected:
List<Set<? extends Set<?>>> list = new ArrayList<Set<? extends Set<?>>>();
list.add(new HashSet<Set<String>>());
list.add(new HashSet<Set<Integer>>());
The problem is that generics is type invariant.
Consider the simpler example:
Animal
to Dog
(e.g. Dog extends Animal
)...
List<Animal>
IS NOT a List<Dog>
List<? extends Animal>
to a List<Dog>
Now here's what happens in this scenario:
Set<?>
to Set<String>
...
Set<Set<?>>
IS NOT a Set<Set<String>>
Set<? extends Set<?>>
to Set<Set<String>>
So if you want a List<T>
where you can add a Set<Set<String>>
, Set<Set<Integer>>
, etc, then T
is NOT Set<Set<?>>
, but rather Set<? extends Set<?>>
.
List<List<? extends Number>>
List<Animal> animals = new ArrayList<Dog>()
?<E extends Number>
and <Number>
?It doesn't compile because the type of the second argument in the Pair<,>
of the statement is String
and that type might not be the "unknown" type that was used in the declaration. I think it will compile if you replace the ?
with Object
. Of course, you will then lose compile-time type-checking.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With