Ссылки на методы
Если лямбда выражения вызывают только один существующий метод, лучше ссылаться на этот метод по его имени. Ссылки на методы (Method References) – это компактные лямбда выражения для методов у которых уже есть имя. Например:
Consumer consumer = str -> System.out.println(str);
можно переписать с помощью method references:
Consumer consumer = System.out::println;
Ссылки на методы бывают четырех видов:
Ссылка на статический метод
Ссылка на нестатический метод конкретного объекта
Ссылка на нестатический метод любого объекта конкретного типа
Ссылка на конструктор
2. Ссылка на статический метод
ContainingClass::staticMethodName
Function function = e -> Boolean.valueOf(e); System.out.println(function.apply("TRUE"));
Перепишем с помощью ссылки:
Function function = Boolean::valueOf; System.out.println(function.apply("TRUE"));
3. Ссылка на нестатический метод конкретного объекта
containingObject::instanceMethodName
Этот тип используется когда лямбда выражение вызывает метод внешнего уже существующего объекта.
Consumer consumer = e -> System.out.println(e); consumer.accept("OCPJP 8");
Перепишем, используя ссылку:
Consumer consumer = System.out::println; consumer.accept("OCPJP 8");
Еще один пример:
Integer integer = 5; Supplier supplier = () -> integer.toString(); System.out.println(supplier.get());
Integer integer = 5; Supplier supplier = integer::toString; System.out.println(supplier.get());
4. Ссылка на нестатический метод любого объекта конкретного типа
ContainingType::methodName
Function function = s -> s.toLowerCase(); System.out.println(function.apply("OCPJP 8"));
Function function = String::toLowerCase; System.out.println(function.apply("OCPJP 8"));
5. Ссылка на конструктор
ClassName::new
ClassName не может быть абстрактным классом или интерфейсом.
Function function = (d) -> new Integer(d); System.out.println(function.apply("4"));
Function function = Integer::new; System.out.println(function.apply("4"));
Что такое ссылки на методы в Java?
Ссылки на методы являются признаком Java 8. Самое большое дополнение в Java8 — это лямбда-выражения. Ссылка на метод — это сокращенный синтаксис выражения лямбда, который выполняет только один метод. Это позволяет нам ссылаться на конструкторы или методы, не выполняя их. Ссылки на методы и Lambda аналогичны тем, что они оба требуют целевого типа, который состоит из совместимого функционального интерфейса. Интерфейс только с одним методом называется функциональным интерфейсом. Например, Comparable, Runnable, AutoCloseable — это некоторые функциональные интерфейсы в Java. Для ссылки на метод используется оператор double colon (: :). Вы можете получить доступ к методу (выражение лямбда), используя нотацию .
Integer::compare
Ссылка на метод может использоваться для указания следующих типов методов:
- Статические методы
- Методы экземпляра
- Конструкторы, использующие новый оператор (TreeSet :: new)
Пример
import Java.util.*; public class TestClass < public static void main(String[] args) < List weekDays = new ArrayList(); weekDays.add("Monday"); weekDays.add("Tuesday"); weekDays.add("Wednesday"); weekDays.add("Thursday"); weekDays.add("Friday"); weekDays.forEach(System.out::println); >>
Ссылки на методы (Method References) — Java: Функции
Ссылка на метод (Method Reference) – это сокращенная форма лямбда выражения для вызова методов. То есть это синтаксический сахар, который делает код короче и проще для чтения. Рассмотрим это на примере. Представьте что у нас есть список элементов, который мы хотим распечатать на экран. Код, выполняющий эту задачу может выглядеть так:
var langs = List.of("ruby", "php", "python", "javascript"); langs.forEach((lang) => System.out.println(lang));
Этот же код можно сделать короче, передавая в метод forEach() ссылку на println() :
var langs = List.of("ruby", "php", "python", "javascript"); langs.forEach(System.out::println);
Поначалу такой синтаксис кажется непривычным. Но со временем, особенно когда в вашем коде будет много лямбда-функций и обработки коллекций, вы увидите насколько этот способ привлекателен своей лаконичностью.
Общий синтаксис ссылки на метод выглядит так:
Name:methodName
Где Name может быть как объектом так и классом, в зависимости от того, ссылку на что мы хотим получить и как это будет использовано потом. Ниже варианты которые мы можем использовать и в комментариях показаны эквиваленты с использованием лямбда-функций.
objectName::methodName // (v) -> objectName.methodName(v) ClassName::staticMethodName // (v) -> ClassName.staticMethodName(v) ClassName::methodName // (v) -> v.methodName()
Последний пример часто применяется с Comparator при сортировках:
var words = List.of("pear", "apple", "banana"); words.sort(Comparator.comparingInt(String::length)); // Эквивалент // words.sort((w1, w2) -> Integer.compare(w1.length(), w2.length())); System.out.println(words); // Outputs: [pear, apple, banana]
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях:
Ссылки на методы. Виды ссылок на методы. Ссылка на статический метод. Ссылка на метод экземпляра
Если лямбда-выражения связываются с функциональным интерфейсом, то методы также могут быть связаны с функциональным интерфейсом. Связь метода с функциональным интерфейсом осуществляется с помощью ссылки на метод.
Если лямбда-выражение может быть передано в некоторый метод как параметр, то ссылка на метод также может быть передана в качестве параметра. С помощью этой ссылки можно обращаться к методу не вызывая его.
В Java различают 4 вида ссылок на методы:
- ссылки на статические методы;
- ссылки на методы экземпляра;
- ссылки на конструкторы;
- ссылки на обобщенные (шаблонные) методы.
2. Ссылка на статические методы
2.1. Общая форма ссылок на статические методы. Разделитель ::
В языке Java можно объявлять ссылки на статические методы. Ссылка на статический метод может быть передана в некоторый метод и там использована для вызова статического метода.
Общая форма объявления ссылки на статический метод следующая:
имя_класса::имя_метода
Разделитель :: внедрен в версии JDK 8 для определения ссылки на метод.
Например. Если в классе A объявлен статический метод с именем Method()
class A < // . static return_type Method(parameters) < // . > >
то ссылка на этот метод будет следующей
A::Method
2.2. Примеры ссылок на статические методы
2.2.1. Ссылка на статический метод вычисления объема шара
Условие задачи. Разработать статический метод, который получает радиус шара и вычисляет объем шара. Реализовать передачу метода вычисления объема шара в другой метод в качестве параметра. Провести тестирование метода.
Решение. При решении данной задачи нужно разработать следующие элементы:
- функциональный интерфейс ICalcFigure . В интерфейсе объявляется единственный метод Volume() , который получает число типа double и возвращает значение типа double ;
- класс CalcVolume() , в котором объявляется статический метод SphereVolume() . Метод получает радиус шара ( double ) и возвращает объем шара ( double )
- класс FigureOperation , в котором объявляется метод Volume() . Этот метод получает два параметра. Первый параметр является ссылкой на интерфейс ICalcFigure . Второй параметр — радиус окружности. По ссылке на ICalcFigure будет передан статический метод вычисления объема шара.
Текст программы, решения данной задачи, следующий.
Результат выполнения программы
Array AI: 1 3 5 8 4 2 Array AI2: 2 4 8 5 3 1
3. Ссылка на методы экземпляра
3.1. Общая форма ссылки на методы экземпляра
Чтобы объявить ссылку на метод экземпляра используется одна из двух общих форм:
имя_экземпляра::имя_метода имя_класса::имя_метода
В другом случае метод экземпляра указывается вмести з любым объектом данного класса, а не только с указанным объектом.
3.2. Примеры использования ссылок на методы экземпляра
3.2.1. Ссылка на методы, выполняющие действия над комплексными числами
Условие задачи. Продемонстрировать передачу в некоторый метод класса методов суммирования и вычитания комплексных чисел.
Решение. Для решения задачи в программе необходимо разработать следующие элементы (составляющие).
1. Класс Complex , определяющий комплексне число
class Complex < // Вещественная и мнимая части комплексного числа public double re; public double im; . >
2. Функциональный интерфейс для оперирования типом Complex
interface IFunction < // Метод, который оперирует комплексными числами типа Complex Complex Function(Complex c1, Complex c2); >
В функциональном интерфейсе объявляется метод Function() . Сигнатура метода определяет получение двух комплексных чисел и возврат комплексного числа. Такая сигнатура может подойти для операций сложения, вычитания, умножения, деления комплексных чисел и других операций.
3. Класс, содержащий собственно методы обработки комплексных чисел (суммирование, вычитание).
class ProcessComplex < // Суммирование комплексных чисел Complex Add(Complex c1, Complex c2) < . > // Вычитание комплексных чисел Complex Sub(Complex c1, Complex c2) < . >>
4. Класс, содержащий метод, который получает ссылку на метод экземпляра. В нашем случае нужно передавать методы Add() и Sub() экземпляра класса ProcessComplex .
class DemoRefMethods < // В этот метод будет передаваться ссылка на методы Add() и Sub() // экземпляра класса ProcessComplex Complex RefMethod(IFunction ref, Complex c1, Complex c2) < . >>
5. Класс, демонстрирующий использование ссылки на метод экземпляра
// 5. Класс, который демонстрирует использование ссылки на метод экземпляра public class RefMethod < public static void main(String[] args) < . >>
Ниже приведен текст решения задачи.
Разница в вызовах заключается в передаче первого параметра, которым есть ссылка на метод экземпляра. В первом случае передается метод экземпляра, который вычисляет среднее арифметическое по следующему синтаксису
Array::Avg
В другом случае передается метод экземпляра
Array::Sum
который вычисляет сумму.
После запуска на выполнение программа выдаст следующий результат
AI = 2 4 8 -1 3 -5 average = 1.8333333333333333 sum = 11.0
Связанные темы
- Ссылка на конструктор класса
- Стандартные (предопределенные) функциональные интерфейсы Java