Проще говоря, лямбда-выражения в Java - это методы, реализованные без тела класса. Но подождите, не все методы можно реализовать как лямбды. Только те, которые объявлены внутри кандидатов функциональных интерфейсов (интерфейс, содержащий только один абстрактный метод), являются привилегированными.

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

Любая реализация функционального интерфейса (как анонимный класс) может быть преобразована в лямбда-выражение.

При внимательном рассмотрении все, что необходимо сделать, - это удалить элементы, которые могут быть неявно доступны компилятору, и разделить параметры и фактическое выражение с помощью оператора ' - ›'.

Давайте рассмотрим простой пример следующего знакомого кода:

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

Теперь давайте удалим ненужные вещи, чтобы получить наше лямбда-выражение. Следующие токены (выделенные жирным шрифтом выше) являются кандидатами на удаление, поскольку они могут быть определены компилятором:

1. новый Comparator ‹String›: потому что имя неявно связано с сигнатурой метода sort, который принимает Collection и Comparator. Тип String выводится из типа параметра list.

2. Тип возвращаемого значения int: так как это тип возвращаемого значения, объявленный с помощью метода.

3. Имя метода compare: имя указывать не нужно, поскольку это единственный метод функционального интерфейса, который необходимо реализовать.

4. Тип параметра String: выводится из сигнатуры метода compare.

Отсюда получаем следующее:

Кроме того, поскольку в данном примере внутри лямбда-выражения только одна строка, мы также можем при желании обойтись -

5. Открывающие и закрывающие фигурные скобки.

6. Ключевое слово return, которое можно определить по типу возвращаемого метода, независимо от того, возвращает ли оно значение или является недействительным.

Таким образом, наш исходный знакомый код становится:

Collections.sort(list, (o1, o2) -> o1.compareTo(o2));

Следующий шаг: ссылки на методы

Не могли бы вы сделать его более кратким?

Почему нет? Если лямбда-выражение просто состоит из вызова метода для его параметров или для какого-либо другого объекта с его параметрами, разве не должно хватить только ссылок на эти методы? Здесь мы идем с примерами преобразований для всех видов -

Тип 1: статические методы.

n -> Math.abs(n)   =>    Math::abs

Параметры лямбда-выражений всегда передаются в качестве аргументов упомянутому методу.

Тип 2: метод экземпляра объекта в параметре

str -> str.length()                         =>    String::length
(str, i) -> str.substring(i)                =>    String::substring
(str, s2, s3) -> str.replaceAll(s2, s3)     =>    String::replaceAll

Этот вид самый интересный из всех. Ссылки на методы олицетворяют ссылки на статические методы из типа 1. Первый параметр лямбда-выражения всегда является объектом, для которого будет вызван указанный метод, а остальные параметры являются аргументами, передаваемыми этому методу по порядку.

Тип 3: метод экземпляра любого произвольного объекта и параметры лямбда-выражения, переданные в качестве аргумента этому методу.

() -> str.length()                   =>    str::length
text -> str.compareTo(text)          =>    str::compareTo
(text, i) -> str.indexOf(text, i)    =>    str::indexOf

Они похожи на Тип 1, за исключением того, что имя класса перед оператором :: было заменено конкретными экземплярами локальных переменных или переменных-членов. Параметры метода являются аргументами по порядку для соответствующих методов, как в Типе 2.

Тип 4: Конструкторы.

name -> new Thread(name)    =>    Thread::new

Идентично ссылкам на статические методы Типа 1.

Давайте вернемся, чтобы увидеть, как наши знакомые ярмарки кода с преобразованием типа 2:

Collections.sort(list, String::compareTo);

Милая, не правда ли? ❤

Для многих это изменение, направленное на привнесение функционального программирования в объектно-ориентированную Java, является обратным сдвигом парадигмы, но, как мы видели в этой статье, это помогает нам сократить шаблонный код и написать простую логику несложным образом. Однако лямбда-выражения не вредит объектно-ориентированной природе Java, если они достаточно просты, чтобы не играть с состояниями включающего класса или пытаться глобальные мутации.

✉️ Подпишитесь на рассылку еженедельно Email Blast от CodeBurst 🐦 Подпишитесь на CodeBurst на Twitter , просмотрите 🗺️ Дорожная карта веб-разработчиков на 2018 год и 🕸️ Изучите веб-разработку с полным стеком .