【发布时间】:2020-08-05 06:41:55
【问题描述】:
我在回答 a question 时遇到了我无法解释的情况。考虑这段代码:
interface ConsumerOne<T> {
void accept(T a);
}
interface CustomIterable<T> extends Iterable<T> {
void forEach(ConsumerOne<? super T> c); //overload
}
class A {
private static CustomIterable<A> iterable;
private static List<A> aList;
public static void main(String[] args) {
iterable.forEach(a -> aList.add(a)); //ambiguous
iterable.forEach(aList::add); //ambiguous
iterable.forEach((A a) -> aList.add(a)); //OK
}
}
我不明白为什么显式输入 lambda (A a) -> aList.add(a) 的参数会使代码编译。此外,为什么它链接到Iterable 中的过载而不是CustomIterable 中的过载?
是否有对此的解释或规范相关部分的链接?
注意:iterable.forEach((A a) -> aList.add(a)); 仅在 CustomIterable<T> 扩展 Iterable<T> 时编译(直接重载 CustomIterable 中的方法会导致模棱两可的错误)
两者都得到这个:
- openjdk版本“13.0.2” 2020-01-14
Eclipse 编译器 - openjdk 版本“1.8.0_232”
Eclipse 编译器
编辑:上面的代码在用maven编译时编译失败,而Eclipse编译最后一行代码成功。
【问题讨论】:
-
这三个都不能在 Java 8 上编译。现在我不确定这是在较新版本中修复的错误,还是引入的错误/功能......你可能应该指定 Java 版本
-
@Sweeper 我最初使用 jdk-13 得到了这个。 Java 8 (jdk8u232) 中的后续测试显示相同的错误。不知道为什么最后一个不能在你的机器上编译。
-
@ernest_k Eclipse 有自己的编译器实现。这可能是该问题的关键信息。此外,在我看来,a clean maven build errors 最后一行应该在问题中突出显示。另一方面,关于链接的问题,可以澄清 OP 也在使用 Eclipse 的假设,因为代码不可重现。
-
虽然我理解这个问题的智力价值,但我只能建议不要创建仅在功能接口上有所不同的重载方法,并期望它可以安全地称为传递 lambda。我不相信 lambda 类型推断和重载的组合是普通程序员能够接近理解的东西。这是一个包含很多用户无法控制的变量的方程。请避免这种情况:)
标签: java generics lambda javac ecj