Какая переменная находится между скобками и стрелкой (->) в лямбде Java? - PullRequest
2 голосов
/ 05 мая 2020

Рекомендуемое IDE исправление сгенерировало следующий код:

    col1.setCellValueFactory(
            (Callback<CellDataFeatures<String, String>, ObservableValue<String>>) param ->
                    new SimpleObjectProperty<>(param.getValue().getValue())
    );

Я не понимаю param между ObservableValue<String>>) и ->. Есть ли подсказка, как это называется, чтобы я мог искать в Интернете более подробную информацию об этом типе кода?

Ниже приведены подписи методов и интерфейса.

void setCellValueFactory(Callback<TreeTableColumn.CellDataFeatures<S, T>, ObservableValue<T>> var1)

public interface Callback<P, R> {
    R call(P var1);
}

PS: Поскольку кто-то сказал мне указать col1, это объект класса TreeTableColumn в JavaFX.

Я думаю, что меня обманули круглые скобки и param не имеет круглых скобок и считает, что значения в скобках являются параметрами. Я ожидал такой формы, как ниже .

enter image description here При внимательном рассмотрении код в круглых скобках - это просто объявления типов, а не переменные ... И это кажется, что скобки для параметров можно опустить, когда параметр только один.

Ответы [ 2 ]

3 голосов
/ 05 мая 2020

param - это параметр, который передается лямбда. Этот код поможет вам понять, что происходит:

Function<String,String> s = (Function<String,String>) param -> {
    System.out.println(param);
    return param;
};
s.apply("Hello World");

Этот код выше без необходимости приводит лямбда к (Function<String, String>).

Если вы измените его на (Function<String,Long>), вы получите ошибка времени компиляции.

0 голосов
/ 05 мая 2020

Вы спросили, что такое param и можно ли его искать. Вы также спросили о «форме» лямбда-выражения (почему круглые скобки присутствуют или нет). Мой ответ ниже отвечает на эти вопросы.

Поиск текста param обычно не работает, так как текст param является произвольным ... вы можете заменить его на p или даже arbitraryName и как пока имя справа от -> в лямбда-выражении изменится на то же значение, код все равно должен работать.

Вы можете думать о param как об имени, присвоенном «переданному» параметр. В объявлении метода ниже есть два параметра (param и anotherParam).

    public void myPrint(String param, String anotherParam) {
        System.out.println(param+", "+anotherParam);
    }

Лямбда-выражение похоже на объявление метода (как указано выше), но ненужный текст можно удалить в синтаксисе лямбда-выражения. Если приведенное выше МОЖЕТ быть преобразовано в лямбда-выражение, оно будет выглядеть следующим образом:

    (String param, String anotherParam) -> { System.out.println(param+", "+anotherParam); }

Обратите внимание, насколько лямбда-выражение похоже на объявление метода. Также обратите внимание, что текст «myPrint» не отображается в приведенном выше тексте. Лямбда-выражение можно рассматривать как объявление "безымянного" метода. В Java лямбда-выражение предоставляет код для реализации SingleAbstractMethod (SAM) в интерфейсе, в котором определен только один абстрактный метод. Предполагая, что у вас есть интерфейс с «MyPrint», определенным как имя SAM, тогда «MyPrint» не требуется (это единственный абстрактный метод в интерфейсе). Лямбда-выражения работают, потому что интерфейс SAM является «функциональным интерфейсом», а лямбда-выражения реализуют SAM в функциональном интерфейсе. В лямбда-выражении имя метода, который вы реализуете, ВСЕГДА не требуется. Это одна из причин, по которой лямбда-выражения трудно понять, поскольку вы обычно понимаете метод по его имени (в некоторой степени), и вы хотели бы искать по имени метода, которое реализует лямбда-выражение, но это имя не отображается в лямбда-код.

Приведенный выше код также может быть записан как ...

 (param, anotherParam) -> { System.out.println(param+", "+anotherParam); }

, если система Java Type может определить типы параметров (в данном случае String) для себя. Опять же, имена param и anotherParam произвольны, но их типы - нет. Они определяются SAM в функциональном интерфейсе, который вы реализуете с помощью лямбда. Другая причина, по которой лямбда-выражения трудны для понимания, заключается в том, что тип параметра (ов) часто интересен ... но он часто опускается в лямбда-выражении, поскольку Java не всегда требуется.

If SAM был нужен только один параметр, лямбда-выражение могло быть записано следующим образом:

 (String param) -> { System.out.println(param); }

, или если "String" может быть определен как Java

 (param) -> { System.out.println(param); }

или даже () не нужны в этой последней версии

 param -> { System.out.println(param); }

Есть и другие упрощения. В некоторых случаях {} справа от -> можно удалить, если это только один оператор или выражение.

Если в реализуемой SAM нет параметров, то код () -> используется, где () означает отсутствие параметров.

Последнее, что я упомяну, что трудно понять в лямбда-выражении, - это большое количество упрощений синтаксиса, которые можно сделать (см. Все выше). Кажется, это основная причина вашего недоразумения.

Итог: лямбда-выражение можно рассматривать как объявление безымянного метода, в котором вы переопределяете SAM в функциональном интерфейсе. Левая часть -> - это объявления параметров ... типы параметров и даже () не всегда нужны. Правая часть -> - это тело метода, а в некоторых случаях {} не нужны.

Ключом к пониманию лямбда-выражения является понимание синтаксиса (все вышеперечисленные формы) и определение и понимание реализуемого функционального интерфейса и SAM. К сожалению, ни функциональный интерфейс, ни имя SAM не отображаются в самом синтаксисе лямбда-выражения ... он упрощен, поскольку в нем нет необходимости!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...