Suppose I have this class hierarchy...public abstract class Animal {    public abstract void eat();    public abstract void talk();}class Dog extends Animal {    @Override    public void eat() {    }    @Override    public void talk() {    }}class Cat extends Animal {    @Override    public void eat() {    }    @Override    public void talk() {    }}And then I have....public static <T extends Animal> void addAnimal(T animal) {    animal.eat();    animal.talk();}public static void addAnimalPoly(Animal animal) {    animal.eat();    animal.talk();}What's the difference when using bounded type parameters or polymorphism?And when to use one or the other?
Java - Use polymorphism or bounded type parameters
java;polymorphism;generics
These two examples are equivalent, and in fact will compile to the same bytecode.There are two ways that adding a bounded generic type to a method as in your first example will do anything.Passing the type parameter to another typeThese two method signatures end up being the same in the byte code, but the compiler enforces type safety:public static <T extends Animal> void addAnimals(Collection<T> animals)public static void addAnimals(Collection<Animal> animals)In the first case, only a Collection (or subtype) of Animal is allowed. In the second case, a Collection (or subtype) with a generic type of Animal or a subtype is allowed.For example, the following is allowed in the first method but not the second:List<Cat> cats = new ArrayList<Cat>();cats.add(new Cat());addAnimals(cats);The reason is that the second one only allows collections of animals, while the first allows collections of any object that is assignable to animal (i.e. subtypes). Note that if this list were a list of animals that happened to contain a cat, either method would accept it: the issue is the collection's generic specification, not what it actually contains.Returning objectsThe other time it matters is with returning objects. Let us assume the following method existed:public static <T extends Animal> T feed(T animal) {  animal.eat();  return animal;}You would be able to do the following with it:Cat c1 = new Cat();Cat c2 = feed(c1);While this is a contrived example, there are cases where it makes sense. Without generics, the method would have to return Animal and you would need to add type casting to make it work (which is what the compiler adds to the byte code anyway behind the scenes).