EDIT: There is another wrinkle in here that I missed that turns out to make a big difference. The method signature of doAnotherThing is instead the following:
<T extends Bar> T doAnotherThing(List<Foo<T>> foo) {
return foo.get(0).doSomething();
}
Disregard the fact that it is a List, just pay attention to the fact that List is a generic class/interface. I’m calling the method like so:
doAnotherThing(new ArrayList<FooImpl>);
So, I have a class and interface defined like so:
abstract class Bar {
// some neat stuff
}
class BarImpl extends Bar {
// some cool stuff
}
interface Foo<T extends Bar> {
T doSomething();
}
class FooImpl implements Foo<BarImpl> {
BarImpl doSomething() {
// Does something awesome
}
}
This is all fine and dandy and works great.
Now, I have a method like so:
<T extends Bar> T doAnotherThing(List<Foo<T>> foo) {
return foo.get(0).doSomething();
}
This method is a generic method in a completely different class and is not part of the chain above.
However, when I try to use this method in the following manner, I’m getting an error saying that the types don’t match:
doAnotherThing(new FooImpl());
FooImpl implements Foo<T>, so I don’t see how this is an error? Maybe I’m misunderstanding something? Thanks
Answer changed to reflect clarification in question
The complilation error (type mismatch) is actually perfectly correct. Note that the method definition says the parameter is a
List<Foo<T>>. This means that the list can contain anyFoo<T>, and the method must even be able to add any object that implementsFoo<T>. And that’s not the case when you give it aList<FooImpl>, because that is only allowed to contain instances ofFooImpl. This works:Mixing generics and polymorphism quickly leads to very complex scenarios, so it should be done sparingly.