Лямбда-выражения в Java.

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

Лямбда-выражения и связанные с ними средства, внедрённые в версии JDK 8, значительно усовершенствовали язык Java по следующим причинам.

Во-первых, они ввели в синтаксис новые элементы, повышающие выразительную силу языка.

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

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

 Несмотря на сходство лямбда-выражений с анонимными классами, их нельзя назвать более удобными синтаксически, чем анонимные классы. В действительности лямбда-выражения реализуются с помощью дескрипторов методов, а также новой специальной инструкции байт-кода JVM, называемой invokedynamic.

В версии Java 7 был внедрён совершенно новый механизм для самоанализа и доступа к методам. Первоначально этот механизм предназначался для применения вместе с динамическими языками, которые могли быть задействованы в диспетчеризации методов во время выполнения. Для поддержки данного механизма на уровне виртуальной машины JVM была внедрена новая байт-кодовая инструкция invokedynamic.

Лямбда-выражения представляют создание объекта особого типа. Тип экземпляра создаваемого объекта называется целевым типом лямбда-выражения. В качестве целевых типов лямбда-выражений допускаются лишь некоторые типы данных.

Целевые типы иначе называют функциональными интерфейсами.

Функциональным называется такой интерфейс, который содержит один и только один абстрактный метод. Как правило, в таком методе определяется предполагаемое назначение интерфейса. Следовательно, функциональный интерфейс представляет единственное действие.

Например, стандартный интерфейс Runnable является функциональным, поскольку в нём определяется единственный метод run(), который в свою очередь, определяет действие самого интерфейса Runnable. Кроме того, в функциональном интерфейсе определяется целевой тип лямбда-выражения. В связи с этим необходимо подчеркнуть следующее: лямбда-выражение можно использовать только в том контексте, в котором определён его целевой тип.

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

  • Должно присутствовать там, где предполагается экземпляр интерфейсного типа.
  • У предполагаемого экземпляра должен быть лишь один обязательный метод.
  • Сигнатура предполагаемого интерфейсного метода должна быть точно такой же, как и у лямбда-выражения.

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

Использование анонимного внутреннего класса для связывания поведения с нажатием кнопки.

button.addActionListener(new ActionListener(){

    public void actionPerformed(ActionEvent event){

        System.out.println("button clicked");

    }

}

Использование лямбда-выражения для связывания поведения с нажатием кнопки

button.addActionListener(event -> System.out.println("button clicked"));

Вместо объекта, реализующего интерфейс, мы передаем блок ко­да - функцию без имени. Здесь event - имя параметра, такое же, как в примере с анонимным внутренним классом, а стрелка  отделяет пара­метр от тела лямбда-выражения, содержащего код, исполняемый при нажатии кнопки.