Scala基于Java 9编译时出现引用歧义错误求助
这个问题我之前碰到过好几次,核心原因是Java 9对java.util.Properties的泛型实现做了调整,再加上Scala的重载解析逻辑和Java的规则略有差异,才导致了这个恼人的歧义错误。
问题根源拆解
Java 9开始,Properties直接实现了Map<Object, Object>,它自身的putAll方法签名是:
void putAll(Map<?, ?> t)
而它的父类Hashtable的putAll签名是:
void putAll(Map<? extends Object, ? extends Object> t)
当你传入java.util.Properties类型的参数时,它同时满足这两个重载的参数类型要求,Scala编译器无法自动判断该选择哪一个,于是抛出歧义错误。
几个可行的解决思路
我整理了几个经过验证的方案,你可以根据自己的代码场景选择:
强制参数匹配Properties的putAll
把传入的props显式转换为Map[_, _]类型,直接匹配Properties自身的方法:newProps.putAll(props.asInstanceOf[java.util.Map[_, _]])这个方法简单直接,只要你确定
props的内容都是合法的键值对,不会有类型安全问题。调用父类Hashtable的版本
如果更倾向于使用父类的实现,可以把newProps强转为Hashtable再调用:newProps.asInstanceOf[java.util.Hashtable[Object, Object]].putAll(props)这种方式适合你明确需要父类方法逻辑的场景。
用Scala集合API中转(更优雅的方式)
借助Scala和Java集合的转换工具,先把Properties转成Scala的Map,再转回Java Map传入:// Scala 2.12及以前用JavaConverters import scala.collection.JavaConverters._ // Scala 2.13+推荐用CollectionConverters // import scala.jdk.CollectionConverters._ newProps.putAll(props.asScala.asJava)这个方法可读性更好,也避免了显式的类型转换,适配不同Scala版本的集合转换工具即可。
手动遍历键值对(最稳妥的方式)
如果担心类型转换带来的潜在问题,可以直接遍历props的键值对逐个put:import scala.collection.JavaConverters._ props.asScala.foreach { case (k, v) => newProps.put(k, v) }这种方式完全避开了重载方法的歧义,逻辑清晰,适合对类型安全要求极高的场景。
内容的提问来源于stack exchange,提问作者Ted

