Более глубокий взгляд на ссылки на методы в Java

Более глубокий взгляд на ссылки на методы в Java

15 марта 2022 г.

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


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


Лямбда-выражения используются для создания анонимных методов.


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


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


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


Ссылка на метод — замечательная функция, представленная в Java 8. Помимо использования преимуществ функционального программирования, одним из самых больших преимуществ использования ссылки на метод является минимизация количества строк кода даже больше, чем лямбда-выражения.


Ссылки на методы — это особый тип лямбда-выражений. Они часто используются для создания простых лямбда-выражений путем ссылки на существующие методы.


Пример 01: Строки в верхнем регистре


```java


импортировать java.util.Arrays;


импортировать java.util.List;


основной класс {


public static void main(String[] args) {


Список фруктов =


Arrays.asList("Яблоко", "Банан", "гуава", "виноград");


фрукты.поток()


.map(String::toUpperCase)


.forEach(System.out::println);


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


```java


фрукты.поток()


.map(String::toUpperCase)


.forEach(фрукты -> System.out.println(фрукты));


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


```java


.forEach(System.out::println);


Объяснение


Давайте подробно рассмотрим, чего мы пытаемся достичь в приведенном выше фрагменте.


  1. У нас есть список фруктов.

  1. Связан с .stream(), поэтому коллекция объектов String преобразуется в Stream объектов String.

  1. Теперь нам нужно связать .stream() с промежуточными операциями, такими как .map(...), который использует справочник по методам, String::toUpperCase заглавными буквами все элементы потока.

  1. Наконец, мы связали его с терминальной операцией .forEach(...), которая также использует ссылку на метод для печати данных.

Чтобы понять, что означают промежуточные и терминальные операции в API потоков, следуйте этим статьям dev.to для лучшего понимания.


  • [Введение в API потоков Java] (https://dev.to/ggorantala/introduction-to-java-streams-api-1d05).

  • [Как работает Streams API? Глубокое погружение в поток операций] (https://dev.to/ggorantala/how-does-streams-api-work-a-deep-dive-on-streamoperation-flow-4e07).

Лямбда-выражения для ссылок на методы


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



Далее мы обсудим различные виды ссылок на методы, их использование, пример фрагмента кода и объяснение.


Типы ссылок на методы


Существует четыре вида ссылок на методы.


  1. Ссылка на статические методы.

  1. Ссылка на методы экземпляра конкретных объектов.

  1. Ссылка на метод экземпляра произвольного объекта определенного типа.

  1. Ссылка на конструктор.

Общий синтаксис


Итак, общий синтаксис для всех этих видов ссылок на методы выглядит следующим образом.


```java


класс/объект::метод


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


Ссылка на статический метод относится к статическому методу для класса. Мы можем использовать ссылку на метод для прямого вызова статических методов. Синтаксис ссылки на статический метод следующий.


Синтаксис


Это классический синтаксис, и это имя класса, за которым следует статический метод, на который вы пытаетесь сослаться.


```java


className:: staticMethodName


Код


Пример фрагмента кода, который объясняет, как статические методы вызываются с помощью ссылок на методы.


Book POJO с конструктором, геттерами и сеттерами.


```java


учебник {


Заголовок строки;


Автор строки;


Целый год;


Целочисленные копииSoldInMillions;


Двойной рейтинг;


Двойная стоимость в евро;


общедоступная книга (название строки, автор строки, целое число года, целое число копий, проданных в миллионах, двойная оценка, двойная стоимость в евро) {


это.название = название;


этот.автор = автор;


этот.год = год;


this.copiesSoldInMillions = копииSoldInMillions;


this.rating = рейтинг;


this.costInEuros = стоимостьInEuros;


публичная строка getTitle () {


вернуть заголовок;


общественный двойной getRating () {


рейтинг возврата;


@Override


общедоступная строка toString () {


вернуть "Книга {" +


"название='" + название + '\'' +


", автор='" + автор + '\'' +


", год=" + год +


", копийПроданоВМиллионах=" + копийПроданоВМиллионах+


", рейтинг=" + рейтинг +


", стоимость в евро = " + стоимость в евро +


BookDatabase для фиктивной инъекции данных.


```java


импортировать java.util.Arrays;


импортировать java.util.List;


открытый класс BookDatabase {


общедоступный статический список<книга> getAllBooks() {


вернуть Arrays.asList(


новая Книга("Дон Кихот", "Мигель де Сервантес", 1605, 500, 3.9, 9.99),


новая книга («Повесть о двух городах», «Чарльз Диккенс», 1859, 200, 3.9, 10.0),


новая книга («Властелин колец», «Дж. Р. Р. Толкин», 2001, 150, 4.0, 12.50),


новая Книга("Маленький принц", "Антуан де Сент-Экзюпери", 2016, 142, 4.4, 5.0),


новая книга («Сон в Красной палате», «Цао Сюэцинь», 1791, 100, 4.2, 10.0)


Ниже приведен наш класс BookApplication, который выполняет императивное программирование или мутации переменной book внутри цикла for, используя ссылку статического метода.


```java


импортировать java.util.List;


открытый класс BookApplication {


public static int compareByTitle (сначала книга, вторая книга) {


вернуть first.getTitle().compareTo(second.getTitle());


public static int compareByRating (сначала книга, вторая книга) {


вернуть first.getRating().compareTo(second.getRating());


public static void main(String[] args) {


List books = BookDatabase.getAllBooks();


System.out.println("СОРТИРОВКА ПО ОЦЕНКАМ: ");


books.sort(BookApplication::compareByRating);


книги.поток()


.map(книга -> book.getTitle() + " -> " + book.getRating())


.forEach(System.out::println);


System.out.println("---------");


System.out.println("СОРТИРОВКА ПО НАЗВАНИЯМ: ");


books.sort(BookApplication::compareByTitle);


книги.поток()


.map(книга -> book.getTitle() + " -> " + book.getRating())


.forEach(System.out::println);


Выход:


Над кодом фрагмент выводит на консоль следующее.


```java


СОРТИРОВКА ПО ОЦЕНКАМ:


Дон Кихот -> 3,9


Повесть о двух городах -> 3.9


Властелин колец -> 4.0


Сон в Красной палате -> 4.2


Маленький принц -> 4.4


СОРТИРОВАТЬ ПО НАЗВАНИЯМ:


Повесть о двух городах -> 3.9


Дон Кихот -> 3,9


Сон в Красной палате -> 4.2


Маленький принц -> 4.4


Властелин колец -> 4.0


2. Ссылка на метод экземпляра конкретного объекта


Ниже приведен пример ссылки на метод экземпляра конкретного объекта:


Синтаксис:


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


```java


объект:: staticMethodName


Код


Пример фрагмента кода, который объясняет, как статические методы вызываются с помощью ссылок на методы.


Для простоты я не дублирую здесь классы Book и BookDatabase, ссылаясь на них в приведенном выше примере.


Итак, давайте сразу перейдем к классу BookApplication.


```java


импортировать java.util.List;


открытый класс BookApplication {


public static void main(String[] args) {


List books = BookDatabase.getAllBooks();


BookApplication bookApplication = new BookApplication();


System.out.println("СОРТИРОВКА ПО ОЦЕНКАМ");


books.sort(bookApplication::compareByRating);


книги.поток()


.map(книга -> book.getTitle() + " -> " + book.getRating())


.forEach(System.out::println);


Система.out.println();


System.out.println("СОРТИРОВКА ПО НАЗВАНИЯМ: ");


books.sort(bookApplication::compareByTitle);


книги.поток()


.map(книга -> book.getTitle() + " -> " + book.getRating())


.forEach(System.out::println);


public int compareByTitle (сначала книга, вторая книга) {


вернуть first.getTitle().compareTo(second.getTitle());


public int compareByRating (первое бронирование, второе бронирование) {


вернуть first.getRating().compareTo(second.getRating());


Выход:


Над кодом фрагмент выводит на консоль следующее.


```java


СОРТИРОВАТЬ ПО ОЦЕНКАМ


Дон Кихот -> 3,9


Повесть о двух городах -> 3.9


Властелин колец -> 4.0


Сон в Красной палате -> 4.2


Маленький принц -> 4.4


СОРТИРОВАТЬ ПО НАЗВАНИЯМ:


Повесть о двух городах -> 3.9


Дон Кихот -> 3,9


Сон в Красной палате -> 4.2


Маленький принц -> 4.4


Властелин колец -> 4.0


Ссылка на метод bookApplication::compareByRating вызывает метод compareByRating, который является частью объекта bookApplication. JRE выводит аргументы типа метода, которыми в данном случае являются (Book book).


Приведенное выше простое объяснение одинаково для этой ссылки на метод bookApplication::compareByTitle.


3. Ссылка на метод экземпляра произвольного объекта определенного типа.


Ниже приведен пример ссылки на метод экземпляра произвольного объекта определенного типа.


Код


Подход 01

```java


импортировать java.util.Arrays;


импортировать java.util.List;


основной класс {


public static void main(String[] args) {


Список фруктов =


Arrays.asList("Банан", "Виноград", "гуава", "яблоки");


fruit.sort(String::compareToIgnoreCase);


фрукты.для каждого(System.out::println);


Выход:

```java


яблоки


Банан


Виноград


гуава


Эквивалентное лямбда-выражение для ссылки на метод String::compareToIgnoreCase будет иметь формальный список параметров (String a, String b), где a и b — произвольные имена, используемые для лучшего описания этого примера. Ссылка на метод вызовет метод a.compareToIgnoreCase(b).


Точно так же ссылка на метод String::concat вызовет метод a.concat(b).


Подход 02

```java


импортировать java.util.Arrays;


импортировать java.util.List;


основной класс {


public static void main(String[] args) {


Список<целых> чисел =


Arrays.asList(11, 4, 2, 8, 9, 10, 32, 22, 20, 17);


числа.поток()


// .sorted((a, b) -> a.compareTo(b)) путь лямбда


.sorted(Целое::сравнить)


.forEach(s -> System.out.print(s + ""));


Выход:

```java


2 4 8 9 10 11 17 20 22 32


4. Ссылка на конструктор


Ссылки на конструкторы — это специальные формы ссылок на методы, которые ссылаются на конструкторы класса. Их можно создать с помощью className и ключевого слова new.


Синтаксис


```java


имя_класса:: новый


Код


```java


открытый класс BookApplication {


public static void main(String[] args) {


BookService bookService = Book::new;


Книга book = bookService.getBook(


"Маленький принц",


«Антуан де Сент-Экзюпери»,


2016, 142,


4.4,


5.0);


System.out.println(книга);


Выход:


```java


Книга{title='Маленький принц', автор='Антуан де Сент-Экзюпери', год выпуска = 2016 год, количество проданных копий – 142, рейтинг – 4,4, стоимость – 5,0}


Здесь собрано все, что вам нужно знать о ссылках на методы в Java.


Удачного кодирования 🤩.


  • Впервые опубликовано [здесь] (https://dev.to/ggorantala/what-are-java-method-references-and-kinds-of-method-references-available-d34)*


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE