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