为何Scala中传入null调用方法时String类比AnyRef类优先级更高?
为什么传入null时String类型的方法重载比AnyRef优先级更高?
这其实是Scala(和Java共享相同的重载解析逻辑)里方法重载匹配规则的典型表现,咱们来一步步理清楚原因:
核心规则:最具体方法优先
当编译器面对多个重载方法都能匹配传入的参数时,会优先选择参数类型最具体的那个版本。
回到你的代码示例:
class Test { def m1(s: String): Unit = { println("String version") } def m1(o: AnyRef): Unit = { println("AnyRef version") } } object Demo { def main(args: Array[String]): Unit = { val t: Test = new Test() t.m1("arun") // 匹配String版本 t.m1(new AnyRef()) // 匹配AnyRef版本 t.m1(null) // 为什么也匹配String版本? } }
1. 类型层级关系
在Scala的类型体系里,String是AnyRef的子类(所有引用类型都直接或间接继承自AnyRef)。这意味着String是比AnyRef更具体的类型——AnyRef可以指代所有引用类型,而String只能指代字符串类型。
2. null的特殊性
null是所有引用类型的合法值,所以它既可以被当作String类型传递,也可以被当作AnyRef类型传递。这时候编译器就需要根据重载规则来选最适合的方法:
- 因为String比AnyRef更具体,所以编译器会优先绑定到参数为String的
m1方法,也就是你看到的输出String version。
反证:如果没有最具体的类型会怎样?
假如我们再给Test类加一个重载方法:
def m1(l: List[Any]): Unit = { println("List version") }
这时候再调用t.m1(null),编译器就会报错——因为String和List[Any]都是AnyRef的子类,它们之间没有继承关系,不存在谁更具体,编译器无法确定该选哪个版本,这也反过来验证了“最具体方法优先”的规则。
内容的提问来源于stack exchange,提问作者Nireekshan
相关产品推荐
相关产品推荐

