Reputation: 37106
Lets research some generic instantion situation using wild card:
This code
List<?> list = new ArrayList<?>();
generates following error:
required: class or interface without bounds
found: ?
But this
List<?> list = new ArrayList< Set<?> >();
compiles succesfully.
and this:
List<Set<?>> list = new ArrayList< Set<?> >();
compiles succesfully too.
but this:
List<Set<Map<?,?>>> list = new ArrayList< Set<Map<String,String>> >();
generates
required: List<Set<Map<?,?>>>
found: ArrayList<Set<Map<String,String>>>
List<Set<?>> list = new ArrayList< HashSet<?> >();
generates
required: List<Set<?>>
found: ArrayList<HashSet<?>>
I am very confusing about these outputs.
I see following regularity:
I can replace ?
from left part on right part only on first level and types should be same inside <> and just ? and ? is forbid.
But I don't understand why?
Can you provide common rules how to instantiate generics using wild card?
Upvotes: 6
Views: 2533
Reputation: 3017
List<?>
a type, which is Set<?>
. Set<?>
is a type.ArrayList<T>
is a subtype of List<T>
.<A extends B>
or <A super B>
stuff). List<String>
is not a subtype of List<Object>
. It is a subtype of List<? extends Object>
or just List<?>
.List<? extends Set<?>>
it would work.Upvotes: 2
Reputation: 178313
Code:
List<?> list = new ArrayList<?>();
Code:
List<?> list = new ArrayList< Set<?> >();
You can use a wildcard as a generic type parameter to a type argument, e.g Set<?>
, a set of anything. Also, any type argument will match the wildcard ?
on the left.
Code:
List<Set<?>> list = new ArrayList< Set<?> >();
The type arguments match, and ?
isn't used directly as in (1) above.
Code:
List<Set<Map<?,?>>> list = new ArrayList< Set<Map<String,String>> >();
This is because even though a Map<String, String>
is a Map<?, ?>
, a List<Set<Map<String, String>>>
is not a List<Set<Map<?, ?>>>
. Java generics are invariant, meaning that type parameters must match; the "is-a" relationship must be specified explicitly with wildcards in upper bounds. E.g. this change compiles, by introducing upper bound wildcards on the left side.
List<? extends Set<? extends Map<?,?>>> list = new ArrayList< Set<Map<String,String>> >();
Code:
List<Set<?>> list = new ArrayList< HashSet<?> >();
Even if a HashSet<?>
is a Set<?>
, because of Java's invariant generics, an ArrayList<HashSet<?>>
is not a List<Set<?>>
. Introducing wildcards on the left as upper bounds works here too:
List<? extends Set<?>> list = new ArrayList< HashSet<?> >();
Upvotes: 4