可以在 Java 中传递指向 Lambda 的引用变量

Can pass reference variable pointing to Lambda in Java

我尝试了一些 Spring 响应式代码,以下是相关代码

Supplier<Stream<Long>> longStreamSupplier = ()
            -> LongStream.iterate(0,
                    nextLong -> nextLong + 1).boxed();

Flux<Long> fooIds = Flux.fromStream(longStreamSupplier); 

上面最后一行给出了 Intellj 中的编译错误 IDE 说没有接受类型的方法。

但是,如果我将其转换为以下内容:

Flux<Long> fooIds = Flux.fromStream(() -> LongStream
                    .iterate(0, nextLong -> nextLong + 1)
                    .boxed());

这很好用。为什么它不能接受指向我在第二段代码中传递的同一个 lambda 表达式的引用变量?

第一个示例中 fromStream 的参数类型错误。 在第二个片段中,它被正确地推断为 Supplier<Stream<? extends Long>>,而在第一个片段中,你明确地 "narrowed" 它下降到 Flux.streamOf.

不接受的东西

您可以通过以下方式修复第一个片段:

        Supplier<Stream<? extends Long>> longStreamSupplier = ()
                -> LongStream.iterate(0,
                nextLong -> nextLong + 1).boxed();

        Flux<Long> stream = Flux.fromStream(longStreamSupplier);

你可能会问自己

Why isn't there an overload for this function which accepts explicitly Supplier<Stream<T>> instead of Supplier<Stream<? extends T>>.

那是因为Java类型擦除,考虑以下两个函数:


    private void foo(Supplier<Stream<? extends  Long>> stream) {

    }
    private void foo(Supplier<Stream<Long>> stream) {

    }

编译时,类型擦除后,我们留下:


    private void foo(Supplier stream) {

    }
    private void foo(Supplier stream) {

    }

这会产生编译错误,因为我们有两个定义相同的函数。所以在Flux::fromStream的情况下,实现了更灵活的版本。

这是因为 longStreamSupplier 变量的类型为 Y<X<A>>,而该方法需要一个类型为 Y<X<? extends A>> 的参数,而这些类型不可互换。

编辑

您可以更改变量类型以使第一个示例编译,

Supplier<Stream<? extends Long>> longStreamSupplier = ..