我有一个重载方法,它采用两个不同的功能接口作为参数(Runnble
和Supplier
)。System.out.println
显然只与 兼容Runnable
,因为它是一种void
方法。然而编译器仍然声称该调用是模棱两可的。这怎么可能?
import java.util.function.Supplier;
public class GenericLambdas {
public static void main(String[] args) {
wrap(System.out::println); // Compiler error here
wrap(() -> {}); // No error
wrap(System.out::flush); // No error
}
static <R> void wrap(Supplier<R> function) {}
static void wrap(Runnable function) {}
}
编译器输出:
Error:Error:line (5)java: reference to wrap is ambiguous
both method <R>wrap(java.util.function.Supplier<R>) in GenericLambdas and method wrap(java.lang.Runnable) in GenericLambdas match
Error:Error:line (5)java: incompatible types: cannot infer type-variable(s) R
(argument mismatch; bad return type in method reference
void cannot be converted to R)
基于第二个错误(argument mismatch, void cannot be converted to R
),编译器不应该能够消除调用的歧义吗?然后,这将处理两个编译器错误(因为它既不会模棱两可,也不会尝试将 void 转换为 R)。
为什么() -> {}
能够System.out::flush
解决?它们具有与 相同的签名System.out.println
。当然,它System.out.println
被带有参数的版本重载,但这些重载版本都不匹配Supplier
or Runnable
,所以我看不出它们在这里有什么关系。
编辑:
似乎这确实可以使用Eclipse 编译器进行编译和运行。哪个编译器是正确的,或者任何一种行为都允许?