Czy odniesienia do metod pomijają obciążenie owijarki lambda? Czy mogą w przyszłości?
Zgodnie z samouczkiem Java na temat metod :
Czasami ... wyrażenie lambda robi tylko wywołanie istniejącej metody. W takich przypadkach często łatwiej jest odnieść się do istniejącej metody według nazwy. Odwołania do metod umożliwiają to; są to zwarte, łatwe do odczytania wyrażenia lambda dla metod, które już mają nazwę.
Wolę składnię lambda od składni odwołania do metody z kilku powodów:
Baranki są wyraźniejsze
Pomimo twierdzeń Oracle, uważam, że składnia lambda jest łatwiejsza do odczytania niż skrót metody obiektowej, ponieważ składnia odwołania do metody jest niejednoznaczna:
Bar::foo
Czy wywołujesz statyczną metodę z jednym argumentem na klasie x i przekazujesz ją x?
x -> Bar.foo(x)
A może wywołujesz metodę wystąpienia z zerowym argumentem na x?
x -> x.foo()
Składnia odwołania do metody może oznaczać jedno lub drugie. Ukrywa to, co faktycznie robi Twój kod.
Jagnięta są bezpieczniejsze
Jeśli odniesiesz się do Bar :: foo jako metody klasy, a Bar później doda metodę instancji o tej samej nazwie (lub odwrotnie), twój kod nie będzie się już kompilował.
Możesz konsekwentnie używać lambdas
Możesz zawinąć dowolną funkcję w lambda - dzięki czemu możesz używać tej samej składni wszędzie. Składnia odwołania do metody nie działa na metodach, które pobierają lub zwracają prymitywne tablice, rzucają sprawdzone wyjątki lub używają tej samej nazwy metody jako instancji i metody statycznej (ponieważ składnia odwołania do metody jest niejednoznaczna co do tego, która metoda zostanie wywołana) . Nie działają, gdy przeciążono metody taką samą liczbą argumentów, ale i tak nie należy tego robić (patrz punkt 41 Josha Blocha), więc nie możemy tego powstrzymać przed odwołaniami do metod.
Wniosek
Jeśli nie ma za to obniżki wydajności, kusi mnie, aby wyłączyć ostrzeżenie w moim IDE i konsekwentnie korzystać ze składni lambda bez rozsypywania okazjonalnych odwołań do metod w moim kodzie.
PS
Ani tu, ani tam, ale w moich snach odwołania do metod obiektowych wyglądają bardziej tak i stosują metodę invoke-dynamic przeciwko metodzie bezpośrednio na obiekcie bez opakowania lambda:
_.foo()
.map(_.acceptValue())
: Jeśli się nie mylę, wygląda to bardzo podobnie do składni Scali. Może po prostu próbujesz użyć niewłaściwego języka.
System.out::println
do forEach()
cały czas ...?