为何Java编译器无法区分Consumer与Collection类型的重载方法?
为何javac无法区分Consumer和Collection类型的重载方法?
先看定义的Java代码:
class Some { void doSome(Consumer<? super Other> consumer) { } <T extends Collection<? super Other>> T doSome(T collection) { doSome(collection::add); // 报错位置 return collection; } }
编译器报错信息:
java: reference to doSome is ambiguous
both method doSome(java.util.function.Consumer<? super Other>) in Some and methoddoSome(T) in Some match
原因解析
这是因为Java编译器处理重载方法调用时,对collection::add这个方法引用的适配存在两种可行的匹配路径,且无法判定哪一个是更合理的目标:
- 第一种匹配:将
collection::add适配为Consumer<? super Other>。Collection的add方法参数类型是? super Other,虽然add返回boolean,但Java允许把有返回值的方法适配到返回void的函数式接口(自动忽略返回值),完全符合第一个doSome方法的参数要求。 - 第二种匹配:尝试匹配泛型方法
doSome(T)。编译器会启动泛型类型推断流程,尝试寻找符合T extends Collection<? super Other>的类型。虽然collection::add本质不是Collection实例,但重载解析阶段会先将该调用纳入候选范围,而Consumer和Collection之间不存在子类型关系,编译器无法确定你要调用哪一个重载,因此抛出“引用模糊”的错误。
解决方法
显式指定方法引用的目标类型,让编译器明确匹配方向:
doSome((Consumer<? super Other>) collection::add);
内容的提问来源于stack exchange,提问作者Jin Kwon
相关产品推荐
相关产品推荐

