在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