Я пытался вписать лямбда-выражения в код, который я пишу, и этот простой пример является следствием того же самого. Для тех, кто не знает о лямбда-выражениях в Java, я бы порекомендовал им сначала прочитать это, прежде чем приступать к этой статье.
Хорошо, теперь, когда вы знакомы с лямбда-выражениями (после прочтения вводного поста), давайте перейдем к простому примеру, который я считаю хорошим использованием лямбда-выражений.
Рассмотрим следующий сценарий: определенная операция окружена некоторой предварительной обработкой и некоторой последующей обработкой. И выполняемая операция может варьироваться в зависимости от
ожидаемое поведение. Код предварительной обработки извлекает необходимые параметры для операции, а последующая обработка выполняет необходимую очистку.
Давайте посмотрим, как это можно сделать с использованием интерфейсов и их реализаций через классы Anonymous Inner.
Использование анонимных внутренних классов
Интерфейс, который должен быть реализован для обеспечения требуемого поведения:
|
1
2
3
|
interface OldPerformer { public void performTask(String id, int status);} |
И давайте посмотрим на метод, который выполняет предварительную обработку, выполняет требуемую операцию и затем последующую обработку:
|
1
2
3
4
5
6
7
8
9
|
public class PrePostDemo { static void performTask(String id, OldPerformer performer) { System.out.println("Pre-Processing..."); System.out.println("Fetching the status for id: " + id); int status = 3;//Some status value fetched performer.performTask(id, status); System.out.println("Post-processing..."); }} |
Нам нужно передать 2 вещи — идентификатор для выполнения предварительной обработки и реализацию операции, что можно сделать, как показано ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class PrePostDemo { public static void main(String[] args) { //has to be declared final to be accessed within //the anonymous inner class. final String outsideOfImpl = "Common Value"; performTask("1234", new OldPerformer() { @Override public void performTask(String id, int status) { System.out.println("Finding data based on id..."); System.out.println(outsideOfImpl); System.out.println("Asserting that the status matches"); } }); performTask("4567", new OldPerformer() { @Override public void performTask(String id, int status) { System.out.println("Finding data based on id..."); System.out.println(outsideOfImpl); System.out.println("Update status of the data found"); } }); }} |
Как видно выше, переменные, объявленные вне внутреннего класса Anonymous, должны быть объявлены как final, чтобы они были доступны в методах внутреннего анонимного класса. Вывод приведенного выше кода будет:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
Pre-Processing...Fetching the status for id: 1234Finding data based on id...Common ValueAsserting that the status matchesPost-processing...Pre-Processing...Fetching the status for id: 4567Finding data based on id...Common ValueUpdate the status of the data foundPost-processing... |
Использование лямбда-выражения
Давайте посмотрим, как написанное выше можно написать с помощью лямбда-выражения:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
public class PrePostLambdaDemo { public static void main(String[] args) { //Need not be declared as final for use within a //lambda expression, but has to be eventually final. String outsideOfImpl = "Common Value"; doSomeProcessing("123", (String id, int status) -> { System.out.println("Finding some data based on"+id); System.out.println(outsideOfImpl); System.out.println("Assert that the status is "+status ); }); doSomeProcessing("456", (String id, int status) -> { System.out.print("Finding data based on id: "+id); System.out.println(outsideOfImpl); System.out.println("And updating the status: "+status); }); } static void doSomeProcessing(String id, Performer performer ){ System.out.println("Pre-Processing..."); System.out.println("Finding status for given id: "+id); int status = 2; performer.performTask(id, status); System.out.println("Post-processing..."); }}interface Performer{public void performTask(String id, int status);} |
Помимо интересного синтаксиса лямбда-выражения, переменная вне области лямбда-выражения не объявляется как окончательная. Но он должен быть в конечном итоге окончательным, что означает, что значение переменной: outsideOfImpl не должно изменяться после объявления.
Это еще один более чистый способ использования лямбда-выражения вместо внутренних классов Anonymous.
Напутствие: выпуск релиза JDK 8 перенесен на февраль 2014 года, а полное расписание можно найти здесь . Я использую лямбда-сборку Project, которая обновляется каждый день, поэтому не стесняйтесь сообщать мне, если что-то из этого не работает в последних сборках. Я буду стараться обновлять сборки и пробовать образцы, размещенные здесь.
Еще одно замечание: не волнуйтесь о том, что происходит в Java 8, эти функции уже являются частью многих языков программирования. Я обнаружил, что изучение синтаксиса и подхода лямбда-выражений в Java помогло мне понять и мыслить функционально и более конкретно оценить замыкания Scala.