如何使用没有原始类型的泛型类型参数编写 Lambda

我有一个带有泛型类型参数的类 Foo


static class Foo<T> {


    T get() {return null;}


    void set(T t) {}


}

我想定义一个 java.util.function.Consumer 的实例,不管它的泛型类型参数如何,它都适用于任何 Foo。消费者将简单地调用 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。


GCT1015
浏览 162回答 3
3回答

沧海一幻觉

另一种解决方法是使用为您提供使用者实例的通用方法。例如:static class Foo<T> {&nbsp; &nbsp; T get() {return null;}&nbsp; &nbsp; void set(T t) {}}public static <T>Consumer<Foo<T>> getFooConsumer() {&nbsp; &nbsp; return foo -> foo.set(foo.get());}public static void main(String[] args) {&nbsp; &nbsp; Consumer<Foo<String>> cons = getFooConsumer();&nbsp; &nbsp; Foo<String> foo = new Foo<>();&nbsp; &nbsp; foo.set("foo!");&nbsp; &nbsp; cons.accept(foo);}请注意,由于您的使用者代码实现目前并没有多大用处,因此根据您的实际需求,很难判断此解决方法是否有任何帮助。您总是可以进一步推动它,并将您选择的值注入到您的已消费中Foo,例如:public static <T>Consumer<Foo<T>> getFooConsumer(T t) {&nbsp; &nbsp; return foo -> foo.set(t);}

函数式编程

无法定义适用于任何泛型类型的实例。泛型类型对于该特定实例必须是已知的,并且是编译器静态类型签名的一部分。这将起作用:Consumer<Foo<Object>>&nbsp;c&nbsp;=&nbsp;(Foo<Object>&nbsp;o)&nbsp;->&nbsp;o.set(o.get());那是该特定通用参数值 (Object) 的一个实例。对于每个单独的类型,您都需要另一个“实例”。说得通?这就像要求一个任何类型的变量。一个变量只有一种类型。在编译时已知。

jeck猫

如果可以编辑Foo,则可以添加一个方法来在内部处理此问题:void update() {&nbsp; &nbsp; set(get());}然后只需使用该方法作为消费者:Consumer<Foo<?>> consumer = Foo::update;否则,我认为静态方法是唯一的方法。您需要避免<?>在set调用点使用 通配符类型,因为您可以传递给无界通配符方法参数的唯一内容是null.
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java