如何在Java中解决重载方法的选择歧义?

package org.study.algos; public class Study { public static void main(String[] args) { A a = new A(); a.m1(null); } } class A { public void m1(String s) { System.out.println("String"); System.out.println(s); } public void m1(Object obj) { System.out.println("Object"); System.out.println(obj); } } 

这里,输出是

String null

为什么JVM将方法解析为带有String参数的方法?

在此先感谢J

这是一个相当精细的算法,详见JLS 15.12 。 但这里相关的部分是15.12.2 ,其中说“选择最具体的部分”。 Object和String重载都是“可访问且适用的”(String适用,因为null文字是所有类型的引用),String更具体。

编辑:修正部分,每个句法。

这些方法“过载”,而不是“模棱两可”。

根据Java语言规范 :

调用方法时(第15.12节),在编译时使用实际参数的数量(以及任何显式类型参数)和参数的编译时类型来确定将被调用的方法的签名( §15.12.2)。

并且§15.12.2说:

可能存在多于一种这样的方法,在这种情况下,选择最具体的方法。

StringObject更具体,因此当null与两者兼容时,选择具有String参数的方法(当参数类型是类或接口层次结构的一部分时,有更复杂的规则适用)。

null值可以设置为任何类型的引用。 您拥有的所有重载方法都在一个inheritance层次结构Object < - String中,正在选择最不常见的方法。 但是如果你有两个不在同一层次结构中的重载方法,那么你会得到关于ambigous方法的编译错误。

String是一个Object,Object不是String,因此第一个重载比第二个更具体 。 参见JLS 15.12.2 ,如提到的Syntactic。

我问了一个类似的问题。 Jon Skeet写了一个很大的答案。

我的问题的链接: 在Java中选择哪个重载为空?