Как передать параметр в функцию поставщика с помощью оператора ссылки на метод (: :) - PullRequest
0 голосов
/ 06 мая 2020

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

private <R> CompletableFuture<R> retryRequest(Supplier<CompletableFuture<R>> supplier, int maxRetries)

Я хочу вызвать эту функцию и передать другой метод (anOtherMethod), который принимает один целочисленный параметр:

CompletableFuture<Boolean> retry = this.retryRequest(this:: anOtherMethod, 2);

Не понимаю, как я могу вызвать этот retryRequest и дать anOtherMethod ( 123)?

Я знаю, что это может работать так:

   CompletableFuture<Boolean> retry = this.retryRequest(()-> anOtherMethod(123), 2);

1 Ответ

1 голос
/ 06 мая 2020

Вы не можете создать лямбда-выражение с определенным c захваченным значением, например 123, в варианте ссылки на чистый метод. . Вам нужно написать явную лямбда-версию со стрелкой, если вы хотите передать захваченные значения, отличные от экземпляра для выполнения метода. Подробнее о захвате значений в лямбдах читайте в этом ответе: Enhanced 'для' l oop и лямбда-выражений

Единственное исключение - объект, который сам становится первым параметром. Предположим, что подпись ожидает Получателя строки:

public void something(Consumer<String> job) {
...

Вышеупомянутая подпись позволит вам написать следующие вызовы:

String myString = " Hey Jack ";
something(myString::trim);
something(s -> s.trim());

Оба делают то же самое, и это, возможно, неинтуитивно, потому что один принимает аргумент (ссылка на экземпляр myString), а другой, похоже, не принимает его (но на самом деле он тоже). Это работает, потому что компилятор пробует два возможных разрешения для ссылки на лямбда-метод (версия выше с ::). С одной стороны, компилятор может применять сигнатуры, как если бы вызываемый метод не имел никаких параметров и не нуждался в передаче. Это случай myString.trim. Но компилятор также проверит, существует ли stati c метод String.trim(myString) (которого, к счастью, нет). Если вы хотите вызвать метод stati c без каких-либо параметров, вам нужно будет вызвать идентификатор класса со ссылкой на функцию следующим образом:

something(String::trim); // this version of trim does not exist.

Иногда это даже проблема, потому что если класс предлагает stati c версию метода и версию, связанную с экземпляром, вы получаете двусмысленность:

public void somethingElse(Function<Integer, String> transformation) {...}

// This will not compile:
somethingElse(Integer::toString);

Приведенный выше пример не будет компилироваться, потому что метод toString существует дважды, один раз как stati c Integer.toString(someInt) и один раз как связанный с экземпляром someInteger.toString().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...