Ламбда-вираз проти посилання на метод [закрито]


114

IntelliJ продовжує пропонувати мені замінити свої лямбда-вирази на посилання на метод.

Чи є якась об'єктивна різниця між ними обома?


4
Насправді я не бачу жодного об’єкта! Це схоже на статичний дзвінок до мене
Джерард

9
Звичайно! Але "ви не знайдете" теж ... Справа в смаку, мене більше хвилювало більше технічних аспектів. Насправді, як ви вже говорили, що вони однакові, це гарна відповідь для мене. У будь-якому випадку, як пропонує IntelliJ, я думаю, що в цілому більше цінується бачити посилання на метод, ніж лямбда (не для мене, однак).
Джерард

15
Код лямбда-виразу компілюється в синтетичний метод, тоді як посилання методів працюють без винятку (виняток: спеціальні конструкції, як Type[]::new). Анонімний клас, створений під час виконання, буде однаковим. JRE не має ніякої різниці між ними. Тож використання посилання на метод дозволить вам заощадити один метод у вашому скомпільованому коді, з іншого боку, ви не можете зупинитися на них, виконуючи покрокову налагодження…
Holger

6
Тепер питання буде закрито ... Шкода для всіх користувачів, як я, які не знають різниці між лямбдами та посиланнями, навіть якщо немає жодного вирішального. Мені також цікаво, чому ніхто не наважився відповісти на це? Це правильна відповідь для мене.
Джерард

3
Відповідь на дворічне закрите запитання - це, мабуть, погана ідея, але для тих, хто АКТУАЛЬНО ПРОЧИТЕ питання, це те, що підручник Oracle ( docs.oracle.com/javase/tutorial/java/javaOO/… ) говорить: Посилання на методи ... компактні, легкі для читання лямбда-вирази для методів, які вже мають назву.
завтра

Відповіді:


187

Дозвольте запропонувати певну точку зору, чому ми додали цю функцію до мови, коли явно нам це не потрібно було (усі методи рефлексу можуть бути виражені як лямбда.)

Зауважте, що правильної відповіді немає . Той, хто каже, що "завжди використовуйте метод ref замість лямбда" або "завжди використовуйте лямбда замість методу ref", слід ігнорувати.

Це питання дуже схоже по духу на "коли я повинен використовувати названий клас проти анонімного класу"? І відповідь одна і та ж: коли вам здається, що це читабельніше . Безумовно, є випадки, які напевно є одним чи неодмінно іншим, але в середині є безліч сірих, і суд повинен використовуватись.

Теорія, що стоїть за методом refs, проста: назви мають значення . Якщо метод має ім'я, то посилання на нього по імені, а не на імперативний мішок коду, який врешті-решт просто обертається і викликає його, часто (але не завжди!) Є більш зрозумілим і читабельним.

Аргументи щодо продуктивності чи про підрахунок персонажів - це переважно червоні оселедці, і їх слід ігнорувати. Мета - написання коду, який є кристально зрозумілим, що він робить. Дуже часто (але не завжди!) Метод виграшів виграє в цій метриці, тому ми включили їх як варіант, який слід використовувати в цих випадках.

Ключовим моментом щодо того, чи уточнюють чи придушують наміри методу refs, є те, чи очевидно з контексту, яка форма функції представляється. У деяких випадках (наприклад, map(Person::getLastName)з контексту зрозуміло, що функція, яка відображає одне на інше, потрібна, а у таких випадках світиться посилання на метод. В інших випадках використання методу ref вимагає від читача запитання про те, який вид функції описується; це попереджувальний знак того, що лямбда може бути читабельнішою, навіть якщо вона довша.

Нарешті, що ми з’ясували, що більшість людей спочатку відволікаються від рефлексу методів, тому що вони відчувають себе ще новішими та дивнішими, ніж лямбда, і тому спочатку вважають їх "менш читабельними", але з часом, коли вони звикають до синтаксису, як правило, змінюють свою поведінку і орієнтуються на посилання на методи, коли можуть. Тому майте на увазі, що ваша власна суб'єктивна початкова "менш читабельна" реакція майже напевно тягне за собою певний аспект упередженості фамільярності, і ви повинні дати собі шанс розслабитися обом, перш ніж висловлювати стилістичну думку.


25
@Gerard Дякую, що ви були б кращою відповіддю.
Яссін Хаджай

3
@Gerard Здається, що Брайан каже "Ні, немає"
dj18

Брайан, я отримую різні результати, використовуючи посилання на метод і лямбда для того ж методу. Чи не повинні вони бути взаємозамінними?
Мішель Файнштейн

@mFeinstein Для кожного методу ref, існує рівнозначна лямбда (яку ви можете або не можете використовувати). Опублікувати код як питання?
Брайан Гец

Я хочу, але я боюся, що код може бути занадто великим, оскільки це Android LiveData, всередині якого Fragment, що я перетворився на такий, Eventякий викликає ViewModel... і інша поведінка відбувається, коли Android повертається до того ж Fragment.. .так мені важко спростити це питання
Мішель Фейнштейн

10

Довгі лямбда-вирази, що складаються з декількох висловлювань, можуть зменшити читабельність вашого коду. У такому випадку вилучення цих висловлювань методом та посилання на нього може бути кращим вибором.

Іншою причиною може бути повторне використання . Замість того, щоб копіювати та вставляти лямбда-вираз із кількох висловлювань, ви можете побудувати метод та викликати його з різних місць вашого коду.


3
Порівняйте: houses.map(House::getName)і houses.map(h -> h.getName()). Лямбда приймає двох менших символів. Це правда, що тип не є явним, але будь-який IDE сказав би вам, і крім того, лямбда повинні використовуватися, коли тип очевидний. Я міг би погодитися з вами щодо використання, але лямбдаси є точно крихітними, тому їх можна прикувати замість створення великих специфічних методів. У цьому сенсі малі методи є більш багаторазовими, ніж якийсь великий і складний метод, і завдяки чіткості лямбда (і певною мірою багатослівності) вони все ще легко читаються.
Джерард

11
Я з Джеральдом. Читання насправді страждає при переміщенні коду, тому вам доведеться перейти до нього, щоб продовжувати читати, а потім стрибати назад. Ви хочете мати весь відповідний код в одному місці. Також Houseє дуже доброякісним прикладом; про що ThreeStoryRedBrickHouseWithBlueDoors. Я віддаю перевагу посиланням методів для багатоаргументних лямбда, а іноді підкреслюю, що лямбда - це лише про один виклик методу. З посиланням на метод менше не можна помилитися: ви можете неправильно написати аргумент на сайті використання, випадково посилаючись на змінну із зовнішньої сфери тощо.
Marko Topolnik

@Gerard Я не згоден з вашим першим твердженням. Якщо ви добре описуєте назви методів і витягуєте великі палі коду, переміщення коду покращує читабельність. Якщо ви використовуєте заплутані назви методів, я згоден з вами.
Торстен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.