Java – Use polymorphism or bounded type parameters

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?

3

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 type

These 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 objects

The 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).

1

Use generics instead of downcasting. “Downcasting” is bad, going from a more general type to a more specific one:

Animal a = hunter.captureOne();
Cat c = (Cat)a;  // ACK!!!!!! What if it's a Dog? ClassCastException!

…you’re trusting that a is a cat, but the compiler can’t guarantee that. It might turn out to be a dog at runtime.

Here’s where you’d use generics:

public class <A> Hunter() {
    public A captureOne() { ... }
}

Now you can specify that you want a cat hunter:

Hunter<Cat> hunterC = new Hunter<Cat>();
Cat c = hunterC.captureOne();

Hunter<Dog> hunterD = new Hunter<Dog>();
Dog d = hunterD.captureOne();

Now the compiler can gurantee that hunterC will only capture cats, and hunterD will only capture dogs.

So just use regular polymorphism if you just want to handle specific classes as their base type. Upcasting is a good thing. But if you get in a situation where you need to handle specific classes as their own type, generically, use generics.

Or, really, if you find you have to downcast then use generics.

EDIT: the more general case is when you want to put off the decision of what kinds of types to handle. So the types become a parameter, as well as the values.

Say I want my Zoo class to handle Cats or Sponges. I don’t have a common super class. But I can still use:

public class <T> Zoo() { ... }

Zoo<Sponge> spongeZoo = ...
Zoo<Cat> catZoo = ...

the degree to which you lock that down is depends on what you’re trying to do 😉

This question is old-ish, but an important factor to consider seems to have been left out regarding when to use polymorphism vs bounded type parameters. This factor may be slightly tangent to the example given in the question but, I feel, very relevant to the more general “When to use polymorphism vs bounded type parameters?”

TL;DR

If you ever find yourself moving code from a subclass to a base class against your better judgment, because of the inability to access it in a polymorphic way, bounded type parameters could be a potential solution.

The Full Answer

Bounded type parameters can expose concrete, non-inherited subclass methods for an inherited member variable. Polymorphism cannot

To elaborate by extending your example:

public abstract class AnimalOwner<T extends Animal> {
   protected T pet;
   public abstract void rewardPet();
}

// Modify the dog class
class Dog extends Animal {
   // ...
   // This method is not inherited from anywhere!
   public void scratchBelly() {
      System.out.println("Belly: Scratched");
   }
}

class DogOwner extends AnimalOwner<Dog> {
   DogOwner(Dog dog) {
     this.pet = dog;
   }

   @Override
   public void rewardPet()
   {
      // ---- Note this call ----
      pet.scratchBelly();
   }
}

If the abstract class AnimalOwner was defined to have a protected Animal pet; and opt for polymorphism, the compiler will error on the pet.scratchBelly(); line, telling you that this method is undefined for Animal.

In your example, you don’t (and shouldn’t) use bounded type. Only use bounded type parameters when you have to, as they are more confusing to understand.

Here are some situation where you will use bounded type parameters:

  • Collections parameters

    class Zoo {
    
      private List<Animal> animals;
    
      public void add(Collection<? extends Animal> newAnimals) {
        animals.addAll(newAnimals);
      }
    }
    

    then you can call

    List<Dog> dogs = ...
    zoo.add(dogs);
    

    zoo.add(dogs) would fail to compile without <? extends Animal>, because generics are not covariant.

  • Subclassing

    abstract class Warrior<T extends Weapon> {
    
      public abstract T getWeapon();
    }
    

    to limit the type subclass can provide.

You can also use multiple bounds <T extends A1 & A2 & A3> to ensure a type is a subtype of all the types in the list.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật