With a single layer of inheritance I can do something like this:
// Dog extends Animal
List<Dog> dogs = ...;
// Cat extends Animal
List<Cat> cats = ...;
List<? extends Animal> animals = new ArrayList<>();
animals.addAll(cats);
animals.addAll(dogs);
I can do this without casting, which is nice.
But what if I have a scenario like the following?
// Plant extends LivingBeing
List<Plant> plants = ...;
// Animal extends LivingBeing
// Cat extends Animal
List<Cat> cats = ...;
List<? extends LivingBeing> livingThings = new ArrayList<>();
// This is fine
lvingThings.addAll(plants);
// FIXME: Fails because Cat doesn't directly extend LivingBeing
livingThings.addAll(cats);
Is there a way to specify an upper bound that is not a direct parent of all members of the list, so that I can avoid casting?
Your first example doesn't compile. Both are caused by the
? extendspart. The issue is that as soon as the initialization is done, the compiler already forgot the actual type. That means that after initializinglivingThings, the compiler thinks it can be aList<LivingBeing>,List<Animal>orList<Cat>(all of which would allow adding cats), but alsoList<Dog> orList`, which don't allow cats.If you want a list with things that can be any type of living being, you must declare it as such:
List<LivingBeing>. Otherwise you can't add anything anymore exceptnull.The latter is true for any
Collection<? extends T>for any typeT. The only value that is safe for any type that matches? extends Tisnull.