为什么这不起作用?
public class FooImpl implements Foo { /* ... */ }
public class Main {
public static <T> Collection<T> getList(Class<? extends T> itemClass) { /* ... */ }
public static void main(String[] args) {
Collection<Foo> foos = getList(FooImpl.class);
}
}
在声明foos
的行上,我收到“Incompatible types. Required: Collection<Foo>, found: Collection<FooImpl>
”错误。知道为什么吗?
答案 0 :(得分:4)
试试这个:
Collection<Foo> foos = Main.<Foo>getList(FooImpl.class);
当你创建getList()
方法时,它会说它将被输入T.并且它还说它需要一个子类型为T的参数(一个T类的子类型是精确的)
由于你从未指定过什么,getList会认为它是FooImpl
所以getList()
会返回FooImpl
的集合。
根据我给你的解决方案,你指定T是Foo
,所以参数需要是Foo
的子类型。例如FooImpl
。
资源:
答案 1 :(得分:3)
因为它返回了FooImpl
的集合,而您希望它返回其超类型的集合。您需要更明确地定义:
public class FooImpl implements Foo { /* ... */ }
public class Main {
public static <S, T extends S> Collection<S> getList(Class<T> itemClass) { /* ... */ }
public static void main(String[] args) {
Collection<Foo> foos = getList(FooImpl.class);
}
}
更新:我不得不提到有一个与此相关的JLS / javac错误导致它在使用“普通香草”javac时无法编译。另请参阅javac bug 6369605,JLS bug 6369608和此related question。然而,它在Eclipe中工作正常。
如果你坚持在Eclipse上使用javac,那么你最安全的赌注是在Java人员修复它之前确实是手动强制方法调用中的返回类型,如Colin Hebert所示。
答案 2 :(得分:1)
将getList
返回类型更改为Collection<? extends T>
FooImpl是Foo的实例
但是
Collection<FooImpl>
是 NOT Collection<Foo>
答案 3 :(得分:0)
我同意BaluC的回答。
只是为了对泛型检查部分The "extends" Wildcard Boundary
中“extends”的基本理解使用带有鞋面的通配符时 限制写入是不安全的 名单。毕竟,汽车永远是一个 车辆,但车辆并不总是一个 车。