我发现我无法调用通配符类型的通用方法而且不明白为什么?
public class GenericsTry2 {
public static class Element {
private Container<? extends Element> container;
public Container<? extends Element> getContainer() {
return container;
}
public void setContainer(Container<? extends Element> container) {
this.container = container;
}
public void doStuff() {
getContainer().doStuff(this); // how to call this?
}
}
public static class SomeSubElement extends Element {
}
public static class SomeSubElement2 extends Element {
}
public static class Container<E extends Element> {
public void doStuff(E element) {
}
}
public static void main(String[] args) {
Container<SomeSubElement2> c = new Container<SomeSubElement2>();
Element e = new SomeSubElement();
c.doStuff((SomeSubElement2) e); // still can do this at compile time this way
}
}
答案 0 :(得分:9)
Container<? extends Element>
表示the Container
can only produce Element
(s), but cannot consume Element
(s)。
原因是? extends Element
表示未知子类型Element
的整个系列。我们假设您将容器设置为Container<SomeSubElement>
。然后,将this
传递给容器(即使您知道它是Element
或子类型Element
)也不正确,因为this
可能是或可能不是SomeSubElement
(取决于运行时类型)。
在泛型世界中,这称为协方差。
为了编译代码(我不保证你需要这个),你可以这样做(注意我已经将容器改为Element
(s)的消费者,而不是制作人):
public class Element {
private Container<? super Element> container;
public Container<? super Element> getContainer() {
return container;
}
public void setContainer(Container<? super Element> container) {
this.container = container;
}
public void doStuff() {
getContainer().doStuff(this);
}
}
但是,如果您需要Container
同时成为制作人和消费者,只需删除通配符并仅使用<Element>
对其进行参数化。
答案 1 :(得分:1)
Container<E extends Element>
表示它包含从E
延伸的Element
内容。不一定是Element
本身。
想象一下,如果你有这样的话会发生什么:
Container<RedElement> redElements = new Container<RedElement>();
Container<E extends Element> container = redElements;
// According to your logic it will work
container.add(new Element());
// Problem here. You just put Element there which is not RedElement.
RedElement element = container.getFirst();
答案 2 :(得分:0)
getContainer()
方法保证返回扩展Element的类的某个对象。因此编译器此时不知道返回的值实际上是Container
类型。如果您要调用doStuff()
- Container
类的方法,则必须明确地将getContainer()
的结果投射到类型Container
。
((Container) getContainer()).doStuff(this);