Wypróbowuję jakiś reaktywny kod Spring, a poniżej znajduje się odpowiedni fragment kodu

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

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

Ostatnia linia powyżej podaje błąd kompilacji w Intellij IDE, mówiąc, że nie ma metody akceptującej typ.

Jeśli jednak przekonwertuję go na następujący:

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

To działa dobrze. Dlaczego nie można zaakceptować zmiennej referencyjnej wskazującej na to samo wyrażenie lambda, które przekazuję w drugim fragmencie kodu?

0
Shailesh Vaishampayan 8 marzec 2020, 13:35

2 odpowiedzi

Najlepsza odpowiedź

Dzieje się tak, ponieważ zmienna longStreamSupplier ma typ Y<X<A>>, podczas gdy metoda oczekuje argumentu typu Y<X<? extends A>>, a te typy nie są zamienne.

edytuj

Możesz zmienić typ zmiennej, aby pierwszy przykład został skompilowany,

Supplier<Stream<? extends Long>> longStreamSupplier = ..
1
Daniele 8 marzec 2020, 11:01

Twój typ argumentu dla fromStream jest nieprawidłowy w pierwszym przykładzie. W drugim fragmencie został poprawnie wydedukowany jako Supplier<Stream<? extends Long>>, podczas gdy w pierwszym wyraźnie „zawęziłeś” go do czegoś, co nie jest akceptowane przez Flux.streamOf.

Możesz naprawić pierwszy fragment kodu, pisząc:

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

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

Możesz zadać sobie pytanie

Dlaczego nie ma przeciążenia dla tej funkcji, która akceptuje jawnie Supplier<Stream<T>> zamiast Supplier<Stream<? extends T>>.

Wynika to z wymazywania typu Java, rozważ następujące dwie funkcje:


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

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

    }

Podczas kompilacji, po usunięciu typu, pozostaje:


    private void foo(Supplier stream) {

    }
    private void foo(Supplier stream) {

    }

Co powoduje błąd kompilacji, ponieważ mamy dwie funkcje z identycznymi definicjami. Tak więc w przypadku Flux::fromStream zaimplementowana jest bardziej elastyczna wersja.

2
adnan_e 8 marzec 2020, 10:49