I can’t figure out what’s wrong with the following code, specifically, why isn’t <A extends ClassA> equivalent to <? extends ClassA>.
Shouldn’t bar() be able to call foo()?
The compiler says The method foo(…) is not applicable for the arguments (…)
(the exact error is specified in a comment below)
static class ClassA {};
static class ClassB<A extends ClassA> {};
private static <A extends ClassA> Collection<ClassB<A>> foo(Collection<ClassB<A>> as) {
return as;
}
private Collection<ClassB<? extends ClassA>> bar(Collection<ClassB<? extends ClassA>> as) {
// Error:
// The method foo(Collection<ClassB<A>>) is not applicable
// for the arguments (Collection<ClassB<? extends ClassA>>)
return foo(as);
}
Thanks!
The problem is that you’re trying to pass something of type
Collection<ClassB<? extends ClassA>>into something of typeCollection<ClassB<A>>. They are not compatible.In order for two generic types to be compatible, their type parameters, if neither is a wildcard, must match exactly. Here, the type parameters are
ClassB<? extends ClassA>andClassB<A>(for someA); neither is a wildcard, and they can never be exactly the same — no matter whatAis, it stands in for a specific type. It is true thatClassB<A>(whateverAis) will be a subtype ofClassB<? extends ClassA>; but that is irrelevant — just likeStringis a subtype ofObjectbutCollection<String>andCollection<Object>are not compatible.If you make
foo()slightly more generic, so that the generic parameter is at the top level:Then you can use capture to do this: