使用带参数的方法引用
Posted
技术标签:
【中文标题】使用带参数的方法引用【英文标题】:Use method reference with parameter 【发布时间】:2015-07-02 08:14:16 【问题描述】:我刚开始学习 Java 流,遇到了一个问题。请看以下示例。这是 Node 类的一部分:
private Map<String, Node> nodes;
public Optional<Node> child(String name)
return Optional.<Node>ofNullable(nodes.get(name));
private void findChildren(String name, List<Node> result)
child(name).ifPresent(result::add);
nodes.values().stream()
// .map(Node::findChildren(name, result))
// .forEach(Node::findChildren(name, result))
.forEach(node -> node.findChildren(name, result));
我的意图是使用流中每个节点上的名称和结果参数调用#findChildren。我尝试使用引用 Node::findChildren 的方法,但没有成功。我会很感激使用 ->
运算符的其他解决方案。
是否可以将方法引用与参数一起使用?我喜欢流的想法,我只是想让代码更具可读性。
实际上,我认为有一个类似的问题Method references with a parameter 我读过,但无法弄清楚如何在我的代码中使用 bind2 方法。它是唯一的解决方案吗?
【问题讨论】:
您只能在需要具有类似签名的功能接口的地方传递方法引用(即可以推断 lambda 的参数) forEach() 需要单个 Node 参数并返回 void,因此只能在此处传递接受单个 Node 的静态方法的引用,或者返回 void 的 Node 类的无参数方法。解决方法:自己创建这样的方法。 marcin-chwedczuk.github.io/method-references-in-java-8 是人们研究带参数的方法引用的一些很好的例子。 【参考方案1】:您不能为此目的使用方法引用。您必须求助于 lambda 表达式。链接问题的bind2
方法不起作用的原因是您实际上是在尝试绑定 两个 参数以将三参数函数转换为单参数函数。没有类似简单的解决方案,因为没有针对三参数消费者的标准函数 interface
。
它必须看起来像
interface ThreeConsumer<T, U, V>
void accept(T t, U u, V v);
public static <T, U, V> Consumer<T> bind2and3(
ThreeConsumer<? super T, U, V> c, U arg2, V arg3)
return (arg1) -> c.accept(arg1, arg2, arg3);
然后.forEach(bind2and3(Node::findChildren, name, result));
可以工作。但这真的比.forEach(node -> node.findChildren(name, result));
简单吗?
【讨论】:
谢谢!带有 2 个参数的Node::findChildren
如何转换为接受 3 个参数的 ThreeConsumer?
对于非static
的方法,你必须把方法接收者算作参数。在您的特定情况下,使用 Node
实例作为参数调用消费者,将在其上调用 findChildren
方法。好吧,如果您使用ClassName::methodName
来引用实例方法,这适用。相反,您可以通过说object::methodName
将方法引用绑定到特定接收器,然后该方法将在object
上调用。发生这种情况,例如当你说System.out::println
时,方法println
将在System.out
中找到的PrintStream
实例上调用。
但在您的情况下,您希望处理不同Node
实例的流,因此您想要让接收器未绑定并将其计为参数。另见here
又是一个令人费解的时刻,只是为了发现“你不能”。以上是关于使用带参数的方法引用的主要内容,如果未能解决你的问题,请参考以下文章