Можете ли вы объяснить, почему первая развернутая ссылка на метод не компилируется? - PullRequest
0 голосов
/ 25 февраля 2019

В этом примере передача ссылки на метод в Stream.of не работает, но после переноса она работает.Я не могу понять, почему это так.Разве ссылка на метод не эквивалентна функциональному интерфейсу?

public class A {

    String a() {
        return "";
    }

    void b() {
        Stream.of(this::a); // won't compile
        Stream.of(wrap(this::a)); // will compile
    }

    static <T> Supplier<T> wrap(Supplier<T> f) {
        return f;
    }
}

Ответы [ 3 ]

0 голосов
/ 25 февраля 2019

Stream.of имеет следующую подпись:

public static<T> Stream<T> of(T t)

Следующий пример будет компилироваться, поскольку вы явно предоставляете информацию о типе для T.

Stream<Supplier<String>> a = Stream.of(this::a);

Первый пример Stream.of(this::a); эквивалентно:

Object a = this::a;

, где Object не является функциональным интерфейсом и не будет компилироваться.

Предоставляя функциональный интерфейс, этот пример компилируется:

Runnable a = this::a;
Stream.of(a);

Во втором примере wrap предоставляет функциональный интерфейс Supplier

0 голосов
/ 28 февраля 2019

this::a не зависит от контекста и может означать разные вещи.Вам нужно предоставить некоторый контекст, чтобы помочь компилятору выяснить, что вы на самом деле имели в виду под this::a.

Stream.<Supplier<String>>of(this::a);

Хотя, похоже, Stream<Supplier<String>> не то, что вы хотели.Если вам нужен Stream<String>, используйте Stream.generate: дополнительная информация о типе не требуется, так как метод принимает Supplier<T> (здесь нет двусмысленности).

Stream.generate(this::a);

На заметку, оба утверждения ожидают, что высохранить свои результаты в переменные.Определение переменных правильного типа часто облегчает решение таких проблем.

Stream<Supplier<String>> s1 = Stream.of(this::a);
Stream<String> s2 = Stream.generate(this::a);

Все благодарности @ J-Alex и @Holger за их ценные комментарии.

0 голосов
/ 25 февраля 2019

Stream.of(T) ожидает Object, и вы передаете ему ссылку на метод в первом операторе.Но параметр Object не является функциональным интерфейсом, поэтому он не может принять ссылку на метод или лямбду, которая не указана специально.
При использовании лямбды это также приведет к ошибке: Stream.of(()->this.a()).
ПрощеПримером может быть Stream.of(()-> "foo"), который просто не будет компилироваться.

Но если вы наберете ссылку на метод или лямбду, это сработает:

Stream.of((Supplier<String>) this::a)

или

Stream.of((Supplier<String>) () -> this.a())

В рабочем операторе вы передаете Stream.of(T) параметрэто Supplier<String>.Это относится к функциональному интерфейсу, но он напечатан, как в предыдущих рабочих примерах, поэтому он действителен как параметр, ожидающий Object.

...