Method references
Тема дорожной карты · Java
Ссылки на методы в Java — это компактный синтаксис для Lambda-выражений, делегирующих существующему именованному методу, что делает код более читаемым и декларативным, когда тело лямбды состоит из единственного вызова метода. Введённые в Java 8 вместе с Lambda-выражениями, ссылки на методы используют оператор :: и бывают четырёх видов: статические (ClassName::staticMethod), связанные с экземпляром (instance::instanceMethod), несвязанные с экземпляром (ClassName::instanceMethod) и конструкторные ссылки (ClassName::new). Ссылки на методы в Java нацелены на те же функциональные интерфейсы — Function, Consumer, Supplier, Predicate, BiFunction и другие из java.util.function — что и Lambda-выражения, и напрямую интегрируются со Stream API для чистых определений конвейеров: list.stream().map(String::toUpperCase).forEach(System.out::println). JVM компилирует ссылки на методы в байткоды invokedynamic, обеспеченные LambdaMetafactory, производящим те же эффективные адаптеры точек вызова, что и эквивалентные Lambda-выражения, без выделения именованного класса. Владение ссылками на методы в Java ведёт к более лаконичному и намерение-выражающему коду при работе с Generics, Collections, коллбэками CompletableFuture и подключением обработчиков событий в Spring или JavaFX.
Как это работает
Method references покрывает generics (параметры типа: class Box<T>, List<String>, Map<K, V>), wildcards (? extends, ? super, правило PECS), функциональные интерфейсы (один abstract-метод: Function, Consumer, Supplier, Predicate), лямбды (x -> x.toUpperCase()), method references (String::toUpperCase), Stream API. Type erasure означает, что generic-инфа исчезает на рантайме — работает на compile-time, но List<String>.class тот же, что List<Integer>.class.
Когда применять
Stream API — для трансформаций (.filter().map().collect()) когда intent яснее цикла. Generics — в API библиотек чтобы протолкнуть type-safety вызывающим. Применяйте PECS (Producer Extends, Consumer Super) при проектировании wildcards. Не over-engineer — Function<? super T, ? extends R> иногда правильный ответ, иногда запах.
Типичные ошибки
Ловушки Method references: List rawList = new ArrayList() (raw-типы — обходят generics, ломают type-safety); злоупотребление Stream .peek() для side-эффектов (это для дебага — forEach если нужны side-эффекты); stateful-лямбды (parallel streams + mutable shared state = race); instanceof + cast вместо pattern matching (Java 21+).