繁体   English   中英

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

[英]How to call generic method of wildcard type in Java?

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

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

    }


}

Container<? extends Element> Container<? extends Element>表示Container只能生成 Element ,但不能使用 Element

原因是这个? extends Element ? 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>对其进行参数化。

Container<E extends Element>意味着它包含从Element扩展的东西E 不一定是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();

getContainer()方法保证返回扩展Element的类的某个对象。 因此编译器此时不知道返回的值实际上是Container类型。 如果要调用Container类的doStuff() Method,则必须将getContainer()的结果显式转换为Container类型。

((Container) getContainer()).doStuff(this);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM