Более глубокий взгляд на ссылки на методы в 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);
Объяснение
Давайте подробно рассмотрим, чего мы пытаемся достичь в приведенном выше фрагменте.
- У нас есть список фруктов.
- Связан с
.stream()
, поэтому коллекция объектов String преобразуется вStream
объектов String.
- Теперь нам нужно связать
.stream()
с промежуточными операциями, такими как.map(...)
, который использует справочник по методам,String::toUpperCase
заглавными буквами все элементы потока.
- Наконец, мы связали его с терминальной операцией
.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).
Лямбда-выражения для ссылок на методы
Вот несколько примеров того, как мы можем заменить лямбда-выражения, используя ссылки на методы.
Далее мы обсудим различные виды ссылок на методы, их использование, пример фрагмента кода и объяснение.
Типы ссылок на методы
Существует четыре вида ссылок на методы.
- Ссылка на статические методы.
- Ссылка на методы экземпляра конкретных объектов.
- Ссылка на метод экземпляра произвольного объекта определенного типа.
- Ссылка на конструктор.
Общий синтаксис
Итак, общий синтаксис для всех этих видов ссылок на методы выглядит следующим образом.
```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
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
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)*
Оригинал