Ссылки на методы
Ссылка на метод (method reference) — это сокращённая запись лямбды, которая
вызывает уже существующий метод. Если лямбда не делает ничего, кроме передачи
аргументов в один метод, её удобно заменить на ссылку через оператор ::.
Код становится короче и часто яснее.
Java различает четыре формы ссылок: на статический метод, на метод конкретного объекта, на метод произвольного объекта типа и на конструктор.
Четыре формы
ClassName::staticMethod // статический метод
object::instanceMethod // метод конкретного объекта
ClassName::instanceMethod // метод произвольного объекта данного типа
ClassName::new // конструктор
Примеры
Пример 1. Ссылка на статический метод
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class StaticRef {
public static void main(String[] args) {
Function<String, Integer> parse = Integer::parseInt;
List<String> raw = Arrays.asList("12", "8", "25");
for (String s : raw) {
System.out.println(parse.apply(s) + 1);
}
}
}
Output:
13
9
26
Пример 2. Ссылка на метод конкретного объекта
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class BoundRef {
public static void main(String[] args) {
List<String> events = Arrays.asList("старт", "стоп", "пауза");
Consumer<String> printer = System.out::println;
events.forEach(printer);
}
}
Output:
старт
стоп
пауза
Пример 3. Ссылка на метод произвольного объекта типа
import java.util.Arrays;
import java.util.List;
public class UnboundRef {
public static void main(String[] args) {
List<String> sensors = Arrays.asList("ик", "Линия", "УЗ");
sensors.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
}
}
Output:
ИК
ЛИНИЯ
УЗ
Пример 4. Ссылка на конструктор
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class ConstructorRef {
static class Sensor {
final String name;
Sensor(String name) { this.name = name; }
@Override public String toString() { return "Sensor(" + name + ")"; }
}
public static void main(String[] args) {
List<String> names = Arrays.asList("ИК", "УЗ", "Линия");
List<Sensor> sensors = names.stream()
.map(Sensor::new)
.collect(Collectors.toList());
System.out.println(sensors);
}
}
Output:
[Sensor(ИК), Sensor(УЗ), Sensor(Линия)]
Пример 5. Сортировка с Comparator.comparing
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class CompareRef {
public static void main(String[] args) {
List<String> items = Arrays.asList("робот", "ИК", "ультразвук", "LED");
items.sort(Comparator.comparing(String::length));
System.out.println(items);
}
}
Output:
[ИК, LED, робот, ультразвук]
Подводные камни
Предупреждение
Ссылка на метод компилируется только если сигнатура метода совместима с сигнатурой абстрактного метода функционального интерфейса.
У перегруженных методов компилятору может не хватить контекста — придётся вернуться к лямбде с явными типами параметров.
ClassName::instanceMethodпринимает экземпляр класса первым аргументом. Это удобно дляstream().map(String::toUpperCase), но иногда сбивает с толку.У
object::methodобъект захватывается один раз — если ссылка хранится долго, объект тоже будет жить.
См. также
Примечание
Материал подготовлен по мотивам Oracle Java Tutorials (Method References) и распространяется в рамках Oracle Free Documentation License. Текст написан своими словами, примеры кода — оригинальные.