2 回答
TA贡献1775条经验 获得超11个赞
参数表达式被认为与潜在适用方法的适用性相关,
m
除非它具有以下形式之一:
一个隐式类型的 lambda 表达式1。
一个不精确的方法引用表达式2。
[...]
所以:
verify("bar", tokens.get("foo", e -> String.valueOf(e)));
在重载解析期间,隐式类型的 lambda 表达式e -> String.valueOf(e)
从适用性检查中跳过 - 两种verify(...)
方法都适用 - 因此存在歧义。
相比之下,这里有一些可行的示例,因为类型是明确指定的:
verify("bar", tokens.get("foo", (Function<Object, String>) e -> String.valueOf(e))); verify("bar", tokens.get("foo", (Function<Object, String>) String::valueOf));
1 - 隐式类型的 lambda 表达式是一个 lambda 表达式,其中推断出其所有形式参数的类型。
2 - 一个不精确的方法引用 - 一个有多个重载的方法。
TA贡献1818条经验 获得超7个赞
有String.valueOf(...)
不同参数的多种实现。编译器不知道你要调用哪一个。编译器无法看到所有可能的方法实际上都返回 a String
,因此调用哪个方法并不重要。由于编译器不知道返回类型是什么,因此它无法推断出Function<...,...>
表达式的类型,因此它无法理解您手头是否会有 aFunction
或其他东西,因此无法判断您是否想调用该get
方法一个Function
或一个Class
。
如果您不String::valueOf
使用 usee -> String.valueOf(e)
那么编译器可以推断出更多,但它仍然不会理解您将始终返回 aString
并因此将其解释为Function<Object, Object>
您的verify
方法有问题。
e -> e.toString
我不完全理解,我不明白为什么编译器不能在String
这里推断为返回类型。它推断Object
并执行与前一个案例完全相同的事情。如果您将操作拆分为
String s = tokens.get("baz", e -> e.toString()); verify("bat", s); // line 21
那么它就可以工作了,因为编译器可以R
从s
. 通过显式指定,它的工作方式相同R
:
verify("bat", tokens.<String>get("baz", e -> e.toString())); // line 21
String.class
编译器很容易理解您要调用该get(Class)
方法。
Object::toString
因为编译器知道这将是一个Function<Object, String>
.
添加回答
举报