Что такое функциональные интерфейсы java
Перейти к содержимому

Что такое функциональные интерфейсы java

  • автор:

Функциональный интерфейс

Чтобы иметь возможность использовать лямбда выражения, необходим интерфейс:

public interface Searchable
Searchable s = (Car c) -> c.getCostUSD() > 20000; 

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

Тип выражения выводится из контекста, в котором используется лямбда выражение. Этот тип называется целевой тип (target type).

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

Одно и то же лямбда выражение может использоваться с разными интерфейсами, если они имеют абстрактные методы, которые совместимы. Например:

interface Searchable < boolean test(Car car); >interface Saleable < boolean approve(Car car); >//. Searchable s1 = c -> c.getCostUSD() > 20000; Saleable s2 = c -> c.getCostUSD() > 20000;

Функциональный интерфейс (functional interface) – это интерфейс у которого только один абстрактный метод. Функциональный интерфейс может содержать любое количество методов по умолчанию (default) или статических методов. Например:

interface A < default int defaultMethod() < return 0; >void method(); >

Еще один пример функционального интерфейса:

interface B < default int defaultMethod() < return 0; >default int anotherDefaultMethod() < return 0; >void method(); >

Функциональный интерфейс может содержать методы класса Object :

interface A

В Java 8 была введена аннотация @FunctionalInterface , которая генерирует ошибку компиляции, если интерфейс не является функциональным:

// This won't compile @FunctionalInterface interface A

Примеры функциональных интерфейсов: java.lang.Runnable , java.util.Comparator.

2. Лямбда vs анонимные классы

Лямбда выражения являются альтернативой анонимным классам. Но они не одинаковы.

  1. Локальные переменные могут быть использованы только если они final или effective final .
  2. Разрешается доступ к переменным класса и статическим переменным класса.
  3. Они не должны выбрасывать больше исключений чем определено в throws метода функционального интерфейса.
  1. Для анонимных классов ключевое слово this ссылается на сам класс. Для лямбды выражений на внешний класс.
  2. Анонимные классы компилируются во внутренние классы. Но лямбда выражения преобразуются в статические private методы класса, в котором они используют invokedynamic инструкцию. Лямбда более эффективны, так как не надо загружать еще один класс.

3. Встроенные функциональные интерфейсы

В Java 8 добавлены встроенные функциональные интерфейсы в пакет java.util.function :

Зачем нужны функциональные интерфейсы в java?

Функциональный интерфейс — это не что-то техническое, что реализуется в языке или виртуальной машине. Это просто абстракция, которая была в Java всегда.

Java задумывалась как исключительно объектно ориентированный язык, поэтому функций в ней никогда не было и нет. Всё поведение располагается в методах. Но для обработчиков событий, например, нужно только поведение, но не состояние, поэтому объект «оборачивающий» метод бесполезен. Обычно обработчик выглядел так:

someButton.addActionListener(new ActionListener() < public void actionPerformed(ActionEvent e) < someTextField.setText("Кнопка нажата"); >>);

ActionListener имеет функциональный интерфейс. То есть интерфейс с одним методом, как бы заявляющий «я не класс, я функция».

В Java 8 просто появились способы более удобно работать с функциональными интерфейсами — в языке появились лямбды, у виртуальной машины появились средства, позволяющие генерировать из лямбд классы с функциональным интерфейсом, а в стандартной библиотеке появился пакет java.util.function, содержащий набор универсальных функциональных интерфейсов , позволяющих передавать и возвращать лямбды между методами в коде разных разработчиков.

Что такое функциональные интерфейсы java

В JDK 8 вместе с самой функциональностью лямбда-выражений также было добавлено некоторое количество встроенных функциональных интерфейсов, которые мы можем использовать в различных ситуациях и в различные API в рамках JDK 8. В частности, ряд далее рассматриваемых интерфейсов широко применяется в Stream API — новом прикладном интерфейсе для работы с данными. Рассмотрим основные из этих интерфейсов:

  • Predicate
  • Consumer
  • Function
  • Supplier
  • UnaryOperator
  • BinaryOperator

Predicate

Функциональный интерфейс Predicate проверяет соблюдение некоторого условия. Если оно соблюдается, то возвращается значение true . В качестве параметра лямбда-выражение принимает объект типа T:

public interface Predicate

import java.util.function.Predicate; public class LambdaApp < public static void main(String[] args) < PredicateisPositive = x -> x > 0; System.out.println(isPositive.test(5)); // true System.out.println(isPositive.test(-7)); // false > >

BinaryOperator

BinaryOperator принимает в качестве параметра два объекта типа T, выполняет над ними бинарную операцию и возвращает ее результат также в виде объекта типа T:

public interface BinaryOperator

import java.util.function.BinaryOperator; public class LambdaApp < public static void main(String[] args) < BinaryOperatormultiply = (x, y) -> x*y; System.out.println(multiply.apply(3, 5)); // 15 System.out.println(multiply.apply(10, -2)); // -20 > >

UnaryOperator

UnaryOperator принимает в качестве параметра объект типа T, выполняет над ними операции и возвращает результат операций в виде объекта типа T:

public interface UnaryOperator

import java.util.function.UnaryOperator; public class LambdaApp < public static void main(String[] args) < UnaryOperatorsquare = x -> x*x; System.out.println(square.apply(5)); // 25 > >

Function

Функциональный интерфейс Function представляет функцию перехода от объекта типа T к объекту типа R:

public interface Function

import java.util.function.Function; public class LambdaApp < public static void main(String[] args) < Functionconvert = x-> String.valueOf(x) + " долларов"; System.out.println(convert.apply(5)); // 5 долларов > >

Consumer

Consumer выполняет некоторое действие над объектом типа T, при этом ничего не возвращая:

public interface Consumer

import java.util.function.Consumer; public class LambdaApp < public static void main(String[] args) < Consumerprinter = x-> System.out.printf("%d долларов \n", x); printer.accept(600); // 600 долларов > >

Supplier

Supplier не принимает никаких аргументов, но должен возвращать объект типа T:

public interface Supplier

import java.util.Scanner; import java.util.function.Supplier; public class LambdaApp < public static void main(String[] args) < SupplieruserFactory = ()->< Scanner in = new Scanner(System.in); System.out.println("Введите имя: "); String name = in.nextLine(); return new User(name); >; User user1 = userFactory.get(); User user2 = userFactory.get(); System.out.println("Имя user1: " + user1.getName()); System.out.println("Имя user2: " + user2.getName()); > > class User < private String name; String getName()< return name; >User(String n) < this.name=n; >>
Введите имя: Том Введите имя: Сэм Имя user1: Том Имя user2: Сэм

Функциональный интерфейс (Functional Interface) — Java: Функции

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

Функциональный интерфейс — это интерфейс с единственным абстрактным методом. Он «под капотом» используется как тип для соответствующих ему лямбда-функций. Создадим для примера такой интерфейс:

@FunctionalInterface public interface Transformer  // Имя метода может быть любым // Количество параметров может быть любым String apply(String input); > 

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

public class LambdaDemo  public static void main(String[] args)  Transformer upperCaseTransformer = (input) -> input.toUpperCase(); var result = upperCaseTransformer.apply("hello"); System.out.println(result); // Outputs: HELLO > > 

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

public class LambdaDemo  // Метод, который принимает лямбду как параметр public static String transform(Transformer fn, String param)  return fn.apply(param); > public static void main(String[] args)  var result = LambdaDemo.transform((input) -> input.toUpperCase(), "hello"); System.out.println(result); // Outputs: HELLO > > 

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *