In Java, polymorphism does NOT apply to generic types. So suppose class Child extends from class Parent, then the following 2 lines, only the first can pass compilation.
Parent var = new Child(); // compiler is happy with this
ArrayList<Parent> myList = new ArrayList<Child>(); // compilation error
The way to bring the idea of inheritance into Java generic types is using <? extends Parent> or <? super Child>. In this article we'll see how to understand the meaning of syntax <? extends Parent> in Java generics.
Check another article on how to understand syntax <? super Child> in Java generics.
1. Basic meaning
<? extends Parent> means any class that see class Parent as its ancestor. Parent can be either a class or an interface. (yes, interface is OK although keyword extends is used)
<? extends Parent> can be used for variables definition and method's parameter
2. Make a collection read-only
If generic types' syntax <? extends Parent> used as method's parameter definition, then the parameter is read-only. Usually it's used with a collection parameter, and that collection is read-only inside the method.
Why ? Let's image you have a method printName defined like
interface Animal{
String getName();
}
class Dog implements Animal { // omit getName implementation }
class Cat implements Animal { // omit getName implementation }
void printName(List<? extends Animal> animals) {
// Good to read from List
for (Animal animal : animals) {
System.out.println (animal.getName());
}
// Error when write to list, compile fail
animals.add(new Dog());
}
The printName has a paramenter animals as type List<? extends Animal>. So the following usage are both correct since Dog and Cat are all subclass of Animal.
printName (new ArrayList<Dog>());
printName (new ArrayList<Cat>());
Now let answer the question about why read-only. In method printName, every element out of list can be guaranteed IS-A type Animal, that's why read from list is OK. But when try to add new element, the compiler has no idea the input list animals has Dog or Cat in it. Because anyone can call this printName method with eight Dog list or Cat list. This information is unknown to compiler, so all the java compiler can do is fail there to avoid making severe mistakes adding a Dog instance into a Cat list.
3. Recap
When use a collection variable with <? extends Parent> style, it means " Hey, I'm gonna use elements in this collection and make sure every one in this collection fulfill IS-A type Parent requirement. But I promise will never ever try to add anything back into this collection"
0 comments:
Post a Comment