Справочник по методу экземпляра и параметры Lambda

У меня возникли проблемы с пониманием синтаксиса для ссылки на метод, где есть два параметра a и b, а ссылка относится к методу a на b.

Например, я понимаю, как

Arrays.sort(personArray, comparators::compareByName);

эквивалентно

Arrays.sort(personArray, (o1, o2) -> comparators.compareByName(o1, o2));

потому что в этом случае параметры лямбда соответствуют параметрам вызова метода (o1, o2).

Однако для этой лямбды

stream.sorted((o1, o2) -> o1.compareToIgnoreCase(o2));

моя IDE говорит мне, что это эквивалентно:

stream.sorted(String::compareToIgnoreCase);

и я не нахожу правила замены этого синтаксиса: a.method(b) ссылкой на метод.

Например, что, если у лямбды есть три или более параметра? Это законно? Становится ли первый параметр целью метода, а остальные параметрами?


person Victor Grazi    schedule 26.08.2014    source источник


Ответы (2)


Я думаю, вы ищете Раздел 15.13.3 JLS, который включает:

Если используется форма ReferenceType :: [TypeArguments] Identifier, тело метода вызова аналогично имеет эффект выражения вызова метода для объявления времени компиляции, которое является объявлением времени компиляции выражения ссылки на метод. Оценка во время выполнения выражения вызова метода, как указано в §15.12.4.3, §15.12.4.4 и §15.12.4.5, где:

  • Режим вызова выводится из объявления времени компиляции, как указано в §15.12.3.

  • Если объявление времени компиляции является методом экземпляра, то целевая ссылка является первым формальным параметром метода вызова. В противном случае целевой ссылки нет.

  • Если объявление времени компиляции является методом экземпляра, то аргументы выражения вызова метода (если есть) являются вторым и последующими формальными параметрами метода вызова. В противном случае аргументы выражения вызова метода являются формальными параметрами метода вызова.

Обратите внимание на последние две пули, в основном.

Например, что, если у лямбды есть три или более параметра? Это законно? Становится ли первый параметр целью метода, а остальные параметрами?

Ага :)

person Jon Skeet    schedule 26.08.2014

Я бы привел здесь пару примеров для тех, кому документация Oracle кажется сложной. Представьте, что вам нужна ссылка на экземпляр Comparator:

.sorted(String::compareTo)

String::compareTo идентичен:

(String a, String b) -> a.compareTo(b);

Потому что, как объяснил Джон, ссылка на метод будет преобразована в лямбду, которая будет ожидать 2 параметра. Фактический произвольный объект, переданный в потоке в качестве первого аргумента, и еще один параметр (поскольку Comparator ожидает int compare(T o1, T o2)). Другой случай:

.map(Employee::getSalary)

В этом случае карта ожидает: Функция. Функция требует реализации R apply(T var1) - метода с 1 аргументом. В этом случае единственным параметром, который будет передан лямбде, является фактический произвольный объект — экземпляр на Employee.

Подводя итог: в зависимости от контекста времени компиляции ссылка на метод для произвольного объекта всегда будет «преобразована» в лямбду, которая ожидает этот объект в качестве первого параметра + любое количество параметров, которые требуется целевому методу в том же соответствующем порядке.

person yuranos    schedule 09.02.2017