Функциональный интерфейс Java8 и лямбда-выражения вы действительно знаете?

Java
Функциональный интерфейс Java8 и лямбда-выражения вы действительно знаете?

эта статьяgithub/JavaMapОн был включен, есть карта расширенных технических знаний Java-программистов и моя серия статей, добро пожаловать в Star.

Выпущенная Oracle в 2014 году, Java8 является самой революционной версией со времен Java5.

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

1. Небольшой испытательный нож Lambda Express

Lambada表达式Это можно понять как:可传递的匿名函数的一种简洁表达方式. Лямбда-выражения не имеют имен и имеют списки параметров, тела функций, типы возвращаемых значений и т. д., как и обычные методы;

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

new Thread(() -> System.out.println("hello java8 lambda")).start()

Класс Thread принимает экземпляр типа Runnable.Глядя на исходный код Jdk, обнаруживается, что интерфейс Runnable является函数式接口, который можно заменить непосредственно лямбда-выражением.

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

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

() -> System.out.println("hello java8 lambda")
  • () В круглых скобках указан список параметров, если параметр только один, его также можно записать так:a -> System.out.println(a)
  • -> Стрелка - фиксированный способ письма;
  • System.out.println("hello java8 lambda") Для тела функции, если имеется несколько операторов, заключите их в фигурные скобки, например:
(a, b) -> {int sum = a + b; return sum;}

Таким образом, модуль выражения Lambda можно закрепить как:

(parameter) -> {expression} 或者 (parameter) -> {statements; statements; }

Только один параметр может опускать круглые скобки

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

// before Java8
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("hello java8 without lambda");
    }
}).start();

2. Расширенное использование Lambda

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

Функциональный интерфейс есть只定义了一个抽象方法的接口. Обратите внимание, что методы по умолчанию (по умолчанию) разрешены в Java 8. Даже если существует много методов по умолчанию, пока есть только один абстрактный метод, интерфейс остается функциональным интерфейсом.

Функциональные интерфейсы обычно имеют аннотацию @FunctionalInterface в классе, например:

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

(2) Что могут делать функциональные интерфейсы?

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

Перед лямбда-выражениями мы обычно использовали匿名内部类Подробное сравнение см. в примере кода в первом подразделе.

(3) Дескриптор функции

Сигнатура абстрактного метода в функциональном интерфейсе в основном является сигнатурой лямбда-выражения, мы можем назвать это соответствие как函数描述符. Очень важно абстрагировать абстрактный метод функционального интерфейса в дескриптор функции, очень легко писать лямбда-выражения, зная дескриптор функции. Например:

Интерфейс Runnable имеет абстрактный метод void run(), который принимает пустые параметры и возвращает void, тогда дескриптор функции можно вывести следующим образом:() -> void

Лямбда-выражение может быть записано как () -> System.out.println("hello java8 lambda")

(4) Часто используемые функциональные интерфейсы

Функциональные интерфейсы обычно используются в java8, а также определены для базового типа java.IntPredicate, LongPredicateПодробности см. в исходном коде jdk.

функциональный интерфейс дескриптор функции
Predicate T->boolean
Consumer T->void
Function<T,R> T->R
Supplier () -> T
UnaryOperator T -> T
BinaryOperator (T,T)->T
BiPredicate<L,R> (L,R)->boolean
BiConsumer<T,U> (T,U)->void
BiFunction<T,U,R> (T,U)->R

Что касаетсяPredicate, Consumer, FunctionКонкретные функции этих функциональных интерфейсов будут подробно представлены в следующих статьях, здесь необходимо только общее впечатление.

(5) Рефакторинг лямбда-выражений в ссылки на методы

方法引用Его можно рассматривать как сокращение для лямбда-выражений, которые могут вызывать метод атрибута как参数传递. Вы также можете рассматривать ссылки на методы как синтаксический сахар для лямбда-выражений, делая лямбда-выражения более лаконичными для написания. Например, отсортированные по возрасту учащихся:

// before
students.sort((s1, s2) -> s1.getAge.compareTo(s2.getAge()))));
// after 使用方法引用
students.sort(Comparator.comparing(Student::getAge()))));

Существует три основных типа ссылок на методы:

  • Ссылка на статический метод

valueOf — это статический метод класса String, а ссылка на метод записывается как String::valueOf, что соответствует лямбда-выражению:a -> String.valueOf(a)

  • Ссылки методов на методы экземпляра любого типа

length — это метод экземпляра класса String, а ссылка на метод записывается как String::length, что соответствует лямбда-выражению:(str) -> str.length()

  • ссылки на методы экземпляров существующих объектов

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

String str = "hello java8";
() -> str.length();

Соответствующая ссылка на метод записывается какstr::length, заметьте, нетString::length

Суммировать

Наконец, мы резюмируем три типа ссылок на методы следующим образом:

лямбда-выражение ссылка на метод
(args) -> ClassName.staticMethod(args) ClassName::staticMethod ссылка на метод статического метода
(arg0, params) -> arg0.instanceMethod(params) ClassName::instanceMethod Справочник по внутреннему методу экземпляра
arg0
(params) -> arg0.instanceMethod(params)
arg0.instanceMethod ссылка на метод внешнего экземпляра

-- END --

Ежедневные лайки: Привет, технари, сначала лайкайте, а потом смотрите, чтобы выработать привычку, ваши лайки — движущая сила на моем пути вперед, а следующий выпуск будет более захватывающим.

Введение: Блогер окончил Хуачжунский университет науки и технологий со степенью магистра, он программист со страстью к технологиям и страстью к жизни. За последние несколько лет он побродил по многим интернет-компаниям первой линии и имеет многолетний опыт разработки.

Публичный номер поиска в Wechat [Архитектор, который любит смеяться], у меня есть технологии и истории, которые ждут вас.

Статья постоянно обновляется вgithub/JavaMapВы можете увидеть мою заархивированную серию статей в , с опытом интервью и техническими галантерейными товарами, добро пожаловать в Star.