简体   繁体   中英

Generics and Wildcards in Java using a static function - “not applicable for the arguments” error

I can't figure out what's wrong with the following code, specifically, why isn't <A extends ClassA> equivalent to <? extends ClassA> <? 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!

I don't know exactly why ... but you need to add a generic type to the second method :)

private <T extends ClassA> Collection<ClassB<T>> bar(Collection<ClassB<T>> as) {
    return foo(as);
}

The problem is that you're trying to pass something of type Collection<ClassB<? extends ClassA>> Collection<ClassB<? extends ClassA>> into something of type Collection<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> ClassB<? extends ClassA> and ClassB<A> (for some A ); neither is a wildcard, and they can never be exactly the same -- no matter what A is, it stands in for a specific type. It is true that ClassB<A> (whatever A is) will be a subtype of ClassB<? extends ClassA> ClassB<? extends ClassA> ; but that is irrelevant -- just like String is a subtype of Object but Collection<String> and Collection<Object> are not compatible.

If you make foo() slightly more generic, so that the generic parameter is at the top level:

private static <T extends ClassB<? extends ClassA>> Collection<T> foo(Collection<T> as) {
    return as;
}

Then you can use capture to do this:

private Collection<? extends ClassB<? extends ClassA>> bar(Collection<? extends ClassB<? extends ClassA>> as) {
    return foo(as);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM