我有以下代码片段:
public static void foo(Object x) {
System.out.println("Obj");
}
public static void foo(String x) {
System.out.println("Str");
}
如果我打电话foo(null)
为什么没有歧义?为什么程序调用foo(String x)
而不是foo(Object x)
?
我有以下代码片段:
public static void foo(Object x) {
System.out.println("Obj");
}
public static void foo(String x) {
System.out.println("Str");
}
如果我打电话foo(null)
为什么没有歧义?为什么程序调用foo(String x)
而不是foo(Object x)
?
为什么程序调用
foo(String x)
而不是foo(Object x)
这是因为String
类扩展自Object
,因此更具体到Object
. 因此,编译器决定调用该方法。请记住,编译器总是选择最具体的方法来调用。请参阅JLS 的第 15.12.5 节
如果多个成员方法既可访问又适用于方法调用,则有必要选择一个为运行时方法分派提供描述符。Java 编程语言使用选择最具体方法的规则。
非正式的直觉是,如果第一个方法处理的任何调用可以传递给另一个方法而不会出现编译时类型错误,那么一个方法比另一个方法更具体。
但是,如果您有两个带有参数 -String
和的方法Integer
,那么您会收到ambiguity
错误null
,因为编译器无法确定哪个更具体,因为它们是非协变类型。
根据null
定义, of 的类型是所有其他引用类型的子类型。引用 JLS 4.1:
空引用始终可以进行扩展引用转换为任何引用类型。
调用中涉及的方法签名的解析遵循所有兼容签名集合中最具体的签名原则。(JLS 15.12.2.5. 选择最具体的方法)。
总之,这意味着String
在您的示例中选择了重载。
它正在调用最具体的方法。
由于 String 是 Object 的子类,因此 String 比 Object 更“具体”。
当在参数对两个参数都有效的两种方法之间进行选择时,编译器将始终选择最具体的参数作为匹配项。在这种情况下,null
是一个可以作为 anObject
和 a处理的文字String
。String
更具体,并且是Object
编译器使用它的子类。