Search code examples
javagenericsinheritancepolymorphism

List of Dogs List of animals... What is the solution?


I stumbled across the same problem as this guy in the related question: Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?

Though I do understand why it is not possible to pass a List<Dog> to a method which accepts List<Animal>, as explained in the answers; I wonder what is ultimately the solution? Suppose I want the method to print the names of the objects in the list, like

public void printNames(List<Animal> list){
   for(Animal a : list){
      System.out.println(a.getName());
   }
}

Given that Animal implements getName(), this method would be safe to call with whatever list of animals or subtypes of that class. Since I can't do that, what is the best way to provide this functionality for whatever list of (sub)animals I might have?

I can say what does not work, which is the obvious way:

public void printNames(List<Dog> list){
   for(Dog d : list){
      System.out.println(d.getName());
   }
}

Because that throws nameClash: Both methods have same erasure


Solution

  • It depends on what you intend to do with the result. Study "PECS" it will help. In this case you can use a wildcard to solve it, but also generic methods and other techniques might be involved.

    public void printNames(List<? extends Animal> list){
       for(Animal a : list){
          System.out.println(a.getName());
       }
    }
    

    You could also just use the toString() method, which might be better.

    public void printAnything(List<?> list){
       for(Object a : list){
          System.out.println(a.toString());
       }
    }