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

114

IntelliJ предлагает мне заменить лямбда-выражения ссылками на методы.

Есть ли между ними объективная разница?

Gerard
источник
4
Не совсем, я не вижу никакого объекта! Для меня это похоже на статический звонок
Джерард
9
Конечно! Но и "не найдешь" ... Это дело вкуса, меня больше волновали технические аспекты. Фактически, поскольку вы уже сказали, что они одинаковы, это хороший ответ для меня. В любом случае, поскольку IntelliJ предлагает это, я думаю, что обычно более ценится видеть ссылку на метод, чем лямбду (хотя не для меня).
Джерард
15
Код лямбда-выражения компилируется в синтетический метод, в то время как ссылки на методы работают без него (исключение: специальные конструкции вроде Type[]::new). Анонимный класс, созданный во время выполнения, будет таким же. JRE не делает между ними никакой разницы. Таким образом, использование ссылки на метод сэкономит вам один метод в вашем скомпилированном коде, с другой стороны, вы не сможете остановиться на них, выполняя пошаговую отладку…
Холгер
6
Теперь вопрос будет закрыт ... Жаль для всех пользователей вроде меня, которые не знают разницы между лямбдами и ссылками, даже если нет решающей. Я также удивляюсь, почему никто не посмел ответить на это? Это правильный ответ для меня.
Gerard
3
Ответ на закрытый вопрос двухлетней давности, вероятно, плохая идея, но для тех, кто ДЕЙСТВИТЕЛЬНО ПРОЧИТАЛ вопрос, это то, что в учебнике Oracle ( docs.oracle.com/javase/tutorial/java/javaOO/… ) говорится: Ссылки на методы ... компактные, легко читаемые лямбда-выражения для методов, у которых уже есть имя.
завтра

Ответы:

188

Позвольте мне предложить некоторые взгляды на то, почему мы добавили эту функцию в язык, когда явно в этом не было особой необходимости (все ссылки на методы могут быть выражены как лямбды).

Обратите внимание, что нет правильного ответа . Следует игнорировать любого, кто говорит «всегда использовать ссылку на метод вместо лямбда» или «всегда использовать лямбда вместо ссылки на метод».

Этот вопрос очень похож по духу на «когда мне следует использовать именованный класс, а не анонимный»? И ответ тот же: когда он станет более читаемым . Конечно, есть дела, которые определенно являются одним или определенно другим, но посередине много серого, и нужно использовать суждение.

Теория, лежащая в основе метода refs, проста: имена имеют значение . Если у метода есть имя, то обращение к нему по имени, а не с помощью обязательного пакета кода, который в конечном итоге просто поворачивается и вызывает его, часто (но не всегда!) Более четкое и читабельное.

Споры о производительности или о подсчете символов в основном отвлекают, и вам следует их игнорировать. Наша цель - написать код, в котором кристально ясно, что он делает. Очень часто (но не всегда!) Ссылки на методы выигрывают по этой метрике, поэтому мы включили их в качестве опции для использования в таких случаях.

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

Наконец, мы обнаружили, что большинство людей сначала избегают ссылок на методы, потому что они кажутся еще более новыми и странными, чем лямбды, и поэтому сначала находят их «менее читаемыми», но со временем, когда они привыкнут к синтаксису, обычно меняют свое поведение и по возможности обращаются к ссылкам на методы. Так что имейте в виду, что ваша собственная субъективная первоначальная «менее читабельная» реакция почти наверняка влечет за собой некоторый аспект предвзятости в отношении фамильярности, и вы должны дать себе возможность освоиться с обоими, прежде чем высказывать стилистическое мнение.

Брайан Гетц
источник
25
@Gerard Спасибо, был бы лучший ответ.
Ясин Хаджадж 03
3
@Gerard Похоже, Брайан говорит: «Нет, нет»
dj18
Брайан, я получаю разные результаты, используя ссылку на метод и лямбду для одного и того же метода. Разве они не должны быть взаимозаменяемыми?
Мишель Файнштейн
@mFeinstein Для каждой ссылки на метод существует эквивалентная лямбда (которую вы можете использовать, а можете и не использовать). Разместите код как вопрос?
Брайан Гетц,
Я хочу, но боюсь, что код может быть слишком большим, так как это Android LiveData, внутри a Fragment, который я преобразовал в, Eventкоторый запускается с помощью ViewModel... и другое поведение происходит, когда Android возвращается к тому же Fragment... .поэтому мне трудно упростить его для вопроса
Мишель Файнштейн
10

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

Другой причиной может быть повторное использование . Вместо того, чтобы копировать и вставлять лямбда-выражение из нескольких операторов, вы можете создать метод и вызывать его из разных мест вашего кода.

овунцетин
источник
3
Сравните: houses.map(House::getName)а houses.map(h -> h.getName()). Лямбда занимает на два символа меньше. Это правда, что тип не является явным, но любая среда IDE сообщит вам об этом, и, кроме того, лямбды следует использовать, когда тип очевиден. Я мог бы согласиться с вами в отношении возможности повторного использования, но лямбды очень маленькие, поэтому их можно связывать в цепочку вместо создания больших конкретных методов. В этом смысле небольшие методы более пригодны для многократного использования, чем некоторые большие и сложные методы, и из-за ясности лямбда-выражений (и в определенной степени многословия) их все еще легко читать.
Gerard
11
Я с Джеральдом. Читаемость на самом деле страдает, когда вы перемещаете код, поэтому вам нужно перейти к нему, чтобы продолжить чтение, а затем вернуться назад. Вы хотите, чтобы весь соответствующий код был в одном месте. Кроме того, Houseэто очень хороший пример; как насчет ThreeStoryRedBrickHouseWithBlueDoors. Я предпочитаю ссылки на методы для лямбда-выражений с несколькими аргументами, а иногда и для того, чтобы подчеркнуть, что лямбда-выражения касается только одного вызова метода. В ссылке на метод меньше ошибок: вы можете неправильно написать аргумент на сайте использования, случайно ссылаясь на переменную из внешней области видимости и т. Д.
Марко Топольник
@ Джерард Я не согласен с вашим первым утверждением. Если вы используете хорошо описывающие имена методов и извлекаете большие груды кода, перемещение кода улучшает читаемость. Если вы используете имена методов обфускации, я с вами согласен.
Торстен