java - wildcard generics in HashSet constructor -
the java hashset
implementation has constructor:
public hashset(collection<? extends e> c) { map = new hashmap<e,object>(math.max((int) (c.size()/.75f) + 1, 16)); addall(c); }
why collection<? extends e> c
? isn't enough: collection<e> c
?
the concept here called variance (covariance, contravariance).
let's have following 2 classes:
class {} class b extends {}
in case, can an instance of b
instance of a
. in other words, following code valid:
a instance = new b();
now, generic classes in java are, default, invariant. means list<b>
not list<a>
. in other words, following code not compile:
list<a> = new arraylist<b>(); // error - type mismatch!
however, if have instance of b, sure can add list of (because b extends a):
list<a> = new arraylist<a>(); as.add(new b());
now, let's have method deals lists of consuming instances:
void printas(list<a> as) { ... }
it tempting make following call:
list<b> bs = new arraylist<b>(); printas(bs); // error!
however, won't compile! if want make such call work, have make sure argument, list<b>
, subtype of type expected method. done using covariance:
void printas2(list<? extends a> as) { ... } list<b> bs = new arraylist<b>(); printas2(bs);
now, method takes instance of list<? extends a>
, , true list<b> extends list<? extends a>
, because b extends a
. concept of covariance.
after introduction, can go constructor of hashset mention:
public hashset(collection<? extends e> c) { ... }
what means following code work:
hashset<b> bs = new hashset<b>(); hashset<a> = new hashset<a>(bs);
it works because hashset<b> hashset<? extends a>
.
if constructor declared hashset(collection<e> c)
, second line on wouldn't compile, because, if hashset<e> extends collection<e>
, not true hashset<b> extends hashset<a>
(invariace).
Comments
Post a Comment