首页 > 解决方案 > 如何使用方法引用运算符(::) 在供应商函数中传递参数

问题描述

抱歉,这在函数式编程中似乎非常基础,但我不明白这个想法。实际上我的代码中有一个方法,它使用一个方法和另一个参数作为参数。

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);

标签: java

解决方案


您不能像123在纯方法引用变体中那样使用特定的捕获值来实例化 lambda。. 如果要传递捕获的值而不是实例来执行方法,则需要使用箭头编写显式 lambda 版本。在此答案中阅读有关在 lambda 中捕获值的更多信息:增强的“for”循环和 lambda 表达式

唯一的例外是对象,它本身成为第一个参数。假设一个签名需要一个字符串的消费者:

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

上面的签名将使您能够编写以下调用:

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

两者都做同样的事情,这可能是不直观的,因为一个接受一个参数(实例引用myString)而一个似乎没有(但它实际上也是如此)。这是可行的,因为编译器为 lambda 方法引用尝试了两种可能的解决方案(上面带有 的版本::)。一方面,编译器可以应用签名,就好像被调用的方法没有任何参数,也不需要传递。对于myString.trim. 但是编译器也会检查是否有静态方法String.trim(myString)(幸运的是没有)。如果您想调用不带任何参数的静态方法,则必须使用函数引用调用类标识符,如下所示:

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

这有时甚至是一个问题,因为如果一个类提供了一个方法的静态版本和一个与实例相关的方法,你就会变得模棱两可:

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

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

上面的例子不会编译,因为该toString方法存在两次,一次是静态的Integer.toString(someInt),一次是实例相关someInteger.toString()的。


推荐阅读