1

我无法弄清楚以下代码有什么问题,具体来说,为什么不<A extends ClassA>等同于<? extends ClassA>.

应该不能bar()打电话foo()吧?

编译器说The method foo(...) is not applicable for the arguments (...)
(确切的错误在下面的评论中指定)

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);
}

谢谢!

4

2 回答 2

2

问题是你试图将一些类型Collection<ClassB<? extends ClassA>>的东西传递给类型的东西Collection<ClassB<A>>。它们不兼容。

为了使两个泛型类型兼容,它们的类型参数(如果两者都不是通配符)必须完全匹配。在这里,类型参数是ClassB<? extends ClassA>and ClassB<A>(for some A); 通配符也不是,它们永远不可能完全相同——不管是什么A,它都代表一个特定的类型。确实ClassB<A>(无论A是什么)将是 ; 的子类型ClassB<? extends ClassA>。但这无关紧要——就像StringObject但不兼容Collection<String>的子类型。Collection<Object>

如果您foo()稍微更通用,以便通用参数位于顶层:

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

然后您可以使用捕获来执行此操作:

private Collection<? extends ClassB<? extends ClassA>> bar(Collection<? extends ClassB<? extends ClassA>> as) {
    return foo(as);
}
于 2012-08-22T20:12:39.630 回答
2

我不知道究竟是为什么...但是您需要将泛型类型添加到第二种方法:)

private <T extends ClassA> Collection<ClassB<T>> bar(Collection<ClassB<T>> as) {
    return foo(as);
}
于 2012-08-22T16:30:55.517 回答