Может передавать ссылочную переменную, указывающую на лямбду, в Java - PullRequest
0 голосов
/ 08 марта 2020

Я пробую какой-нибудь реактивный код 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());

Это прекрасно работает. Почему он не может принять ссылочную переменную, указывающую на то же самое лямбда-выражение, которое я передаю во второй части кода?

Ответы [ 2 ]

2 голосов
/ 08 марта 2020

Ваш тип аргумента для fromStream неверен в первом примере. Во втором фрагменте он был правильно выведен как Supplier<Stream<? extends Long>>, тогда как в первом вы явно «сузили» его до чего-то, что не принимается Flux.streamOf.

Вы можете исправить первый фрагмент, написав:

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

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

Вы можете спросить себя

Почему нет перегрузки для этой функции, которая явно принимает Supplier<Stream<T>> вместо 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 реализована более гибкая версия.

1 голос
/ 08 марта 2020

Это потому, что переменная longStreamSupplier имеет тип Y<X<A>>, а метод ожидает аргумент с типом Y<X<? extends A>>, и эти типы не являются взаимозаменяемыми.

edit

вы можете изменить тип переменной, чтобы компилировать первый пример,

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