如何在Java中调用通配符类型的泛型方法?

Suz*_*ioc 4 java generics wildcard

我发现我不能调用通配符类型的泛型方法而且不明白为什么?

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

    }


}
Run Code Online (Sandbox Code Playgroud)

Kon*_*kov 9

Container<? extends Element>手段是Container只能产生 Element(一个或多个),但不能消耗 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您需要Container同时成为生产者和消费者,只需删除通配符并<Element>仅将其参数化.