Синтаксис лямбда-выражений
Рассмотрим предыдущий пример сортировки еще раз. Мы передаем код, который проверяет, какая строка короче. Мы вычисляем
Integer.compare(firstStr.length(), secondStr.length())
Что такое firstStr и secondStr? Они оба строки! Java является строго типизированным языком, и мы должны указать типы:
(String firstStr, String secondStr)
-> Integer.compare(firstStr.length(),secondStr.length())
Вы только что видели ваше первое лямбда-выражение! Такое выражение является просто блоком кода вместе со спецификацией любых переменных, которые должны быть переданы в код. Почему такое название? Много лет назад, когда еще не было никаких компьютеров, логик Алонзо Чёрч хотел формализовать, что значит для математической функции быть эффективно вычисляемой. (Любопытно, что есть функции, которые, как известно, существуют, но никто не знает, как вычислить их значения.) Он использовал греческую букву лямбда (λ), чтобы отметить параметры. Если бы он знал о Java API, он написал бы что-то не сильно похожее на то, что вы видели, скорее всего.
Почему буква λ? Разве Чёрч использовал все буквы алфавита? На самом деле, почтенный труд Principia Mathematica использует символ ˆ для обозначения свободных переменных, которые вдохновили Чёрча использовать заглавную лямбда (Λ) для параметров. Но, в конце концов, он переключился на строчной вариант буквы. С тех пор, выражение с переменными параметрами было названо «лямбда-выражение».
Вы только что видели одну форму лямбда-выражений в Java: параметры, стрелку -> и выражение. Если код выполняет вычисление, которое не вписывается в одно выражение, запишите его так же, как вы бы написали метод: заключенный в {} и с явными выражениями return. Например,
(String firstStr, String secondStr) -> {
if (firstStr.length() < secondStr.length()) return -1;
else if (firstStr.length() > secondStr.length()) return 1;
else return 0;
}
Если лямбда-выражение не имеет параметров, вы все равно ставите пустые скобки, так же, как с методом без параметров:
() -> { for (int i = 0; i < 1000; i++) doWork(); }
Если типы параметров лямбда-выражения можно вывести, можно опустить их. Например,
Comparator comp
= (firstStr, secondStr) // Same as (String firstStr, String secondStr)
-> Integer.compare(firstStr.length(),secondStr.length());
Здесь компилятор может сделать вывод, что firstStr и secondStr должны быть строками, потому что лямбда-выражение присваивается компаратору строк. (Мы посмотрим на это присваивание повнимательнее позже.)
Если метод имеет один параметр выводимого типа, вы можете даже опустить скобки:
EventHandler listener = event ->
System.out.println("The button has been clicked!");
// Instead of (event) -> or (ActionEvent event) ->
Вы можете добавить аннотации или модификатор final к параметрам лямбды таким же образом, как и для параметров метода:
(final String var) -> ...
(@NonNull String var) -> ...
Вы никогда не указываете тип результата лямбда-выражения. Это всегда выясняется из контекста. Например, выражение
(String firstStr, String secondStr) -> Integer.compare(firstStr.length(), secondStr.length())
может быть использовано в контексте, где ожидается результат типа int.
Обратите внимание, что лямбда-выражение не может возвращать значение в каких-то ветках, а в других не возвращать. Например, (int x) -> { if (x <= 1) return -1; } является недопустимым.
Do'stlaringiz bilan baham: |