Ответ 1
Вы не можете заменить lambda input -> getValueProvider().apply(input).getValue()
ссылкой на метод без изменения семантики.
Ссылка на метод заменяет один вызов метода, поэтому он не может просто заменить лямбда-выражение, состоящее из более чем одного вызова метода.
Лямбда-выражение формы input -> getValueProvider().apply(input)
может быть заменено на getValueProvider()::apply
, если и только если время оценки getValueProvider()
не имеет значения, как в лямбдной форме, метод вызывается на каждой оценке лямбда-тела, тогда как для ссылки на метод он вызывается только один раз и результат улавливается.
Это похоже на разницу между x -> System.out.println(x)
и System.out::println
, где чтение содержимого поля System.out
происходит в разное время, но обычно это не имеет значения. Но вы должны знать разницу.
В вашем примере вызывается третий метод getValue()
. Единственный способ выразить это с помощью ссылок на методы требует функционального интерфейса, такого как Function
, который имеет такие методы, как andThen
и/или compose
. Тем не менее, как работает Java 8, для чего требуется, чтобы первая ссылка метода на целевой интерфейс вызывала метод объединения, который отнюдь не будет легче читать, что теперь у вас есть лямбда-выражение: ((Function<X,Y>)getValueProvider()::apply).andThen(Y::getValue)
где Y
тип, apply(input)
возвращает.
Обратите внимание, что правило гласит: "Замените лямбда с помощью ссылок на методы, когда это возможно", что дает вам возможность сказать "ну, здесь это невозможно", однако я не уверен, как много вы можете называть это "правилом" тогда...