好的,所以方法重载是一件坏事™。既然这个问题已经解决了,让我们假设我实际上想重载一个像这样的方法:
static void run(Consumer<Integer> consumer) {
System.out.println("consumer");
}
static void run(Function<Integer, Integer> function) {
System.out.println("function");
}
在Java7中,我可以很容易地使用不明确的匿名类作为参数来调用它们:
run(new Consumer<Integer>() {
public void accept(Integer integer) {}
});
run(new Function<Integer, Integer>() {
public Integer apply(Integer o) { return 1; }
});
// Consumer
run((Integer i) -> {});
// Function
run((Integer i) -> 1);
// Consumer
run(i -> {});
// Function
run(i -> 1);
但这不能编译。编译器(javac,JDK1.8.0_05)不喜欢这样:
Test.java:63: error: reference to run is ambiguous
run(i -> {});
^
both method run(Consumer<Integer>) in Test and
method run(Function<Integer,Integer>) in Test match
对我来说,直觉上,这没有意义。在产生返回值(“value-compatible”)的lambda表达式和产生void
(“void-compatible”)的lambda表达式之间绝对没有歧义,如JLS§15.27所述。
但当然,JLS是深入和复杂的,我们继承了20年向后兼容的历史,并且有一些新的东西,如:
某些包含隐式类型的lambda表达式(§15.27.1)或不精确的方法引用(§15.13.1)的参数表达式被适用性测试忽略,因为它们的含义在选定目标类型之前无法确定。
摘自《联合法典》第15.12.2节
上面的限制可能与JEP 101没有完全实现有关,这里和这里可以看到。
我想您在编译器中发现了这个bug:JDK-8029718(或者Eclipse中的这个类似的:434642)。
请参阅JLS§15.12.2.1。确定可能适用的方法:
…
注意“void
兼容块”和“值兼容块”之间的明确区别。虽然在某些情况下,一个块可能是两者兼而有之,但第15.27.2节。Lambda正文明确指出,像()->{}
这样的表达式是一个“void
兼容块”,因为它通常完成时不会返回值。很明显,i->{}
也是一个“void
兼容块”。
根据上面引用的部分,带有不兼容值的块的lambda和带有(non-void
)返回类型的目标类型的组合不是方法重载解析的潜在候选项。所以你的直觉是对的,这里不应该有任何歧义。
不明确块的示例有
() -> { throw new RuntimeException(); }
() -> { while (true); }
因为它们不能正常完成,但你的问题不是这样的。
问题内容: 我正在尝试学习Lambda表达式, 已经为int和float类型重载了operator(),我确定使用Lambda表达式应该可以做到这一点,但似乎不太可能找出问题所在: 请让我知道我在这里做错了什么,并提出解决方法… 更新: 好的,所以我了解了 功能性接口 的概念,我的问题也是关于实现上述代码中我想做的事情,并且发现了几种实现方法。 感谢您的宝贵回答! 问题答案: 甲功能接口必须是一个
问题内容: 假设我有一个通用接口: 和方法sort: 我可以调用此方法并将lambda表达式作为参数传递: 那会很好的。 但是现在,如果我将接口设为非泛型,并且将方法设为泛型: 然后像这样调用: 它不会编译。它在lambda表达式中显示错误: “目标方法是通用的” 好的,当我使用编译时,它显示以下错误: 从此错误消息看来,编译器似乎无法推断类型参数。是这样吗 如果是,那为什么会这样呢? 我尝试了各
它不编译。它在lambda表达式中显示错误: “目标方法是泛型的” 好的,当我使用编译它时,它显示了以下错误:
我在这里有一段代码,基本上只是创建一个等于参数的线程数,在每个线程中实例化一个MyRunnable对象,将线程添加到线程列表中,然后根据for循环的迭代设置线程的名称。 我的问题是,有没有更干净的方法?是否可以使用流将此功能封装在lambda中?
IntelliJ一直建议我用方法引用替换我的lambda表达式。 两者之间有什么客观差异吗?
用Java 8 lambdas到处乱搞。为什么当我向接口添加另一个方法时,这会给我一个错误: 不使用第二个方法也能正常工作:“public int getID(String name)