In Java, while arrays are covariant, collections are invariant. For example, given that a Foo
is a Bar
, while we have a Foo[]
is a Bar[]
, we do not have that a Collection<Foo>
is a Collection<Bar>
. This implies that we cannot pass in a Collection<Foo>
where a Collection<Bar>
is needed. Why?
The reason is that a Collection<Foo>
cannot do everything a Collection<Bar>
can do, thus a Collection<Foo>
is indeed not a Collection<Bar>
. Take String
and Object
as an example. One thing a Collection<Object>
can do but a Collection<String>
cannot do is to add an Object
to the collection. Yes, we can add a String
to a Collection<Object>
, but we cannot add an Object
to a Collection<String>
. This is the rule of the sub-type polymorphism in Java: a String
is an Object
, but an Object
is not a String
.
A corollary of the above reasoning could be a Collection<? extends Bar>
is not a Collection<Bar>
. This is so because only the null
literal can be added to a Collection<? extends Bar>
through either add()
or addAll()
(See the Java Language Specification 3.0, §5.1.10, Capture Conversion.), while both the null
literal and Bar
s can be added to a Collection<Bar>
. As a result, a Collection<Bar>
is not assignable from a Collection<? extends Bar>
.
Note that a Collection<? extends Bar>
is assignable from either a Collection<Foo>
or a Collection<Bar>
, because either of them can do everything the Collection<? extends Bar>
can do.
Finally, and of course, a Collection<Bar>
is not a Collection<Foo>
, even though a Foo can be added to either of them.
Post new comment