I am just trying to understand the extends
keyword in Java Generics.
List<? extends Animal>
means we can stuff any object in the List
which IS A Animal
then won't the following also mean the same thing:
List<Animal>
Can someone help me know the difference between the above two? To me extends
just sound redundant here.
Thanks!
super is a lower bound, and extends is an upper bound.
Generic Classes and Subtyping Using the Collections classes as an example, ArrayList<E> implements List<E>, and List<E> extends Collection<E>. So ArrayList<String> is a subtype of List<String>, which is a subtype of Collection<String>.
Remarks. The List<T> class is the generic equivalent of the ArrayList class.
List<Dog>
is a subtype of List<? extends Animal>
, but not a subtype of List<Animal>
.
Why is List<Dog>
not a subtype of List<Animal>
? Consider the following example:
void mySub(List<Animal> myList) { myList.add(new Cat()); }
If you were allowed to pass a List<Dog>
to this function, you would get a run-time error.
EDIT: Now, if we use List<? extends Animal>
instead, the following will happen:
void mySub(List<? extends Animal> myList) { myList.add(new Cat()); // compile error here Animal a = myList.get(0); // works fine }
You could pass a List<Dog>
to this function, but the compiler realizes that adding something to the list could get you into trouble. If you use super
instead of extends
(allowing you to pass a List<LifeForm>
), it's the other way around.
void mySub(List<? super Animal> myList) { myList.add(new Cat()); // works fine Animal a = myList.get(0); // compile error here, since the list entry could be a Plant }
The theory behind this is Co- and Contravariance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With