我有一个带有通用类型参数的Foo类
static class Foo<T> {
T get() {return null;}
void set(T t) {}
}
我想定义一个适用于ANY Foo的java.util.function.Consumer实例,无论其泛型类型参数如何。使用者只需在Foo实例上调用set方法,并传入get方法返回的值。我决定使用Lambda来实现使用者:
Consumer<Foo> compilesButWithWarnings = foo -> foo.set(foo.get());
不幸的是,我收到有关此实现的警告。警告是:
The method set(Object) belongs to the raw type Foo.
References to generic type Foo<T> should be parameterized.
如果我尝试将我的lambda写为:
Consumer<Foo<?>> compileError = foo -> foo.set(foo.get());
代码将不再编译,并显示错误消息:
The method set(capture#1-of ?) in the type Foo<capture#1-of ?> is not
applicable for the arguments (capture#2-of ?)
我可以想到的一种无需警告即可编译的解决方案是:
Consumer<Foo<?>> worksButRequiresStaticMethod = Test::setFoo;
static <ANY> void setFoo(Foo<ANY> foo) {
foo.set(foo.get());
}
目前还可以,但有点冗长。如果可能的话,我想知道是否有一种更好的方式编写此代码而不会发出警告,也不会更改Foo。
非常感谢您。
答案 0 :(得分:0)
另一个解决方法是使用为您提供使用者实例的通用方法。
例如:
static class Foo<T> {
T get() {return null;}
void set(T t) {}
}
public static <T>Consumer<Foo<T>> getFooConsumer() {
return foo -> foo.set(foo.get());
}
public static void main(String[] args) {
Consumer<Foo<String>> cons = getFooConsumer();
Foo<String> foo = new Foo<>();
foo.set("foo!");
cons.accept(foo);
}
请注意,由于您的消费者代码实现目前并没有太大用处,因此很难确定此变通办法是否会对您有所帮助,这取决于您的实际需求。
您始终可以将其进一步推动,然后将选择的值注入消耗的Foo
中,例如:
public static <T>Consumer<Foo<T>> getFooConsumer(T t) {
return foo -> foo.set(t);
}
答案 1 :(得分:0)
如果您可以编辑Foo
,则可以添加一种内部处理方法:
void update() {
set(get());
}
然后仅使用该方法作为使用者:
Consumer<Foo<?>> consumer = Foo::update;
否则,我认为静态方法是唯一的方法。您需要避免在调用<?>
时使用set
通配符类型,因为唯一可以传递给无界通配符方法参数的是null
。
答案 2 :(得分:0)
不能定义可以与任何泛型类型一起使用的实例。对于该特定实例,泛型类型必须是已知的,并且是编译器静态类型签名的一部分。
这将起作用:
Consumer<Foo<Object>> c = (Foo<Object> o) -> o.set(o.get());
这是该特定通用参数值(对象)的实例。
每种单独的类型都需要另一个“实例”。
有道理吗?
这就像要求一个任何类型的变量。
变量只有一种类型。在编译时已知。