我读了一些关于泛型,通配符和遗产的内容。但仍然无法弄清楚为什么在行getFoo()。doit(this); 有人可以解释为什么会发生这种情况,以及正确的方法是什么?
public class A<T> {
private Foo<T, ? extends A<T>> foo;
public Foo<T, ? extends A<T>> getFoo() {
return foo;
}
public void setFoo(Foo<T, ? extends A<T>> foo) {
this.foo = foo;
}
}
public class B extends A<Integer>{
public B() {
setFoo(new Bar());
getFoo().doit(this);
}
}
public class Bar implements Foo<Integer, B> {
@Override
public void doit(B a) {
System.out.println("some process");
}
}
public interface Foo<T, V extends A<T>> {
public void doit(V a);
}
答案 0 :(得分:0)
在方法调用中,您不允许将非空值作为通配符extends
参数提供(在您的情况下为getFoo().doit(<? extends A<Integer> a)
)。原因是编译器无法知道原始通用定义是什么,因此它将拒绝编译代码。
您的问题可以用simle List<?>
:
public static List<Integer> myList = new ArrayList<Integer>();
public static List<? extends Number> getList() {
return myList;
}
public static void main() {
getList().add(Integer.valueOf(1000)); // Can not substitute wildcard by Integer
}
上面的代码看起来完全正常(除了编译错误:)),但想象一下:
public static void main() {
getList().add(Long.valueOf(1000)); // This would definitely cause ClassCastException later when someone calls myList.get(0)
}
更新要解决您的问题,您需要摆脱通配符,例如在类定义中添加另一个类型参数:
public class A<T, V extends A<T, V>> {
private Foo<T, V> foo;
public Foo<T, V> getFoo() {
return foo;
}
public void setFoo(Foo<T, V> foo) {
this.foo = foo;
}
}
public class B extends A<Integer, B>{
public B() {
setFoo(new Bar());
getFoo().doit(this);
}
}