Given that a foo is a bar, why is a foo collection not a bar collection?

Given that a foo is a bar, why is a foo collection not a bar collection?

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 Bars 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

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.

More information about formatting options

To prevent automated spam submissions leave this field empty.