【发布时间】:2020-07-21 17:32:33
【问题描述】:
考虑以下几点:
public void run() {
run(o -> {});
}
//replace CharSequence with whatever except Object
public <E extends CharSequence> void run(E e) {
}
public <E extends CharSequence> void run(Consumer<E> e){
}
编译器会抱怨java reference to run is ambiguous,即使传递的参数显然是一个 lambda,而这两个方法中只有一个是 lambda
问题是为什么会这样?它是一个错误吗?应该用什么替换签名以实现相同的行为?
额外:
IntelliJ 说(Main 类无关紧要):
Ambiguous method call. Both
run(CharSequence) in Main and
run(Consumer<CharSequence>) in Main match
注意:
用除java.lang.Object 之外的任何东西替换CharSequence 都会产生同样的问题!
另请注意:
即使两个泛型不同并且彼此不相关也没关系!只要他们不是java.lang.Object。
所以,这不会编译 ether:
public void run() {
run(o -> {});
}
public <E extends ArrayList> void run(E e) {
}
public <E extends String> void run(Consumer<E> e){
}
【问题讨论】:
-
The same behaviour语句包括:参数赋值中没有强制转换,仍然使用泛型类型,保持同名同类 -
我得到一个不同的编译错误,它是
The target type of this expression must be a functional interface。 (Java 11.0.6) -
“非正式的直觉是,如果第一个方法处理的任何调用可以传递给另一个方法而不会出现编译时错误,那么一个方法比另一个方法更具体。”根据这个定义,这两种方法都没有更具体,因此它们是模棱两可的。
-
是的,我也明白了。
-
“即使传递的参数显然是一个 lambda,而这两种方法中只有一个是 lambda” - 这是不正确的。它们都不是 lambda。你对 lambdas 有一个基本的误解。 lambda 创建一个接口的实例,因此它可以在任何需要普通(功能)接口的地方使用。
Consumer是一个接口,E也可以是一个。