What <E extends Animal & IQuadruped>
means is "a particular type that is a subtype of both Animal
and IQuadruped
", and not "any type that is a subtype of both Animal
and IQuadruped
"
The reason it's difficult to grasp the difference is that in everyday thinking we don't make that distinction explicit. If for example you agree to go out for lunch with someone in a restaurant, and they say "any day next week is good for me", you automatically know that means you need to turn up on the same day. And not that you can go at any time and they'll be there.
In this case there's no guarantee that the E
the caller chooses will definitely be Dog
, so your code won't work.
The obvious wrong solution is to specify<E extends Dog>
, because it would guarantee that E
is a subtype of Dog
. However this is wrong for the exact same reason, E
could be any subtype of Dog
, let's say E
is a Poodle
, so when you create a List<Poodle>
, you won't be able to put your new Dog()
in there, because it isn't a Poodle
.
The correct bound is <E super Dog>
, because that means E
is definitely a type that you can cast a Dog
instance to. It could be Dog
itself, it could be Animal
or IQuadruped
or even Object
. But it guarantees that you can put a Dog
in the list.
The name of this principle is PECS: producer extends, consumer super, and you can read about it here.