编程语言
首页 > 编程语言> > 在Java泛型中共享通配符

在Java泛型中共享通配符

作者:互联网

假设我有一个界面

interface Foo<T> { 
    void foo(T x); 
    T bar() 
}

以及具有未知参数的这种类型的对象:Foo<?>巴兹.然后我可以调用baz.foo(baz.bar()).

但是,现在我需要将值baz.bar()放入一个集合中,稍后再调用它上面的baz.foo().就像是

List<???> list; // can I tell the compiler this is the same type as baz's wildcard?
list.add(baz.bar());
...
baz.foo(list.get(1));

这也不起作用:

List<Object> list;
list.add(baz.bar());
...
baz.foo((???) list.get(1)); // I can't write down the type I need to cast to

有没有办法做到这一点?

编辑:以上是从我的实际情况过分简化.说我们有

class Bar {
    private final Foo<?> foo;
    private List<???> list; // the type argument can be selected freely

    Bar(Baz baz) {
        foo = baz.getFoo(); // returns Foo<?>, can't be changed 
    }

    void putBar() {
        list.add(foo.bar());
    }

    void callFoo() {
        foo.foo(list.get(0));
    }
}

解决方法:

这是一个尴尬的问题.

解决方案是找到一个范围,它包含通配符的使用,在其上放置一个类型变量,用对类型变量的引用替换通配符,然后绑定类型变量.

在你的情况下,听起来这个类是必要的范围.所以:

public class Whatever<T> {
    private List<T> list;
    private Foo<T> baz;

    public void bazToList() {
        list.add(baz.bar());
    }

    public void listToBaz() {
        baz.foo(list.get(1));
    }
}

问题是你已经在类中添加了一个类型变量.现在,在使用这个类的任何地方,任何提及它的类型都需要有一个类型绑定(所以Whatever< String>或Whatever<?>).如果使用该类的代码并不真正关心它在列表中保留的事物的类型,那可能会令人难以置信.

要解决这个问题,您可以创建一个通用的持有者类.就像是:

public class Whatever {
    private WhateverHolder<?> holder;

    public void bazToList() {
        holder.bazToList();
    }

    public void listToBaz() {
        holder.listToBaz();
    }

    private static class WhateverHolder<T> {
        private List<T> list;
        private Foo<T> baz;

        public void bazToList() {
            list.add(baz.bar());
        }

        public void listToBaz() {
            baz.foo(list.get(1));
        }
    }
}

但那很难看.你正在引入一个全新的类,以及一个新对象的运行时开销,只是为了解决一些恼人的泛型.

标签:java,generics,bounded-wildcard
来源: https://codeday.me/bug/20190715/1470365.html