我有以下代码段:
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)
?
答案 0 :(得分:21)
为什么程序会调用
foo(String x)
而不是foo(Object x)
这是因为String
类从Object
延伸,因此更具体到Object
。因此,编译器决定调用该方法。请记住,编译器总是选择最具体的方法来调用。见Section 15.12.5 of JLS
如果多个成员方法都可访问且适用于a 方法调用,有必要选择一个提供 运行时方法调度的描述符。 Java编程 language使用选择最具体方法的规则。
非正式的直觉是一种方法更具体 如果可以传递第一个方法处理的任何调用,则为另一个 没有编译时类型错误的另一个。
但是,如果您有两个带参数的方法 - String
和Integer
,则ambiguity
会出现null
错误,因为编译器无法确定哪个是{{1}}更具体,因为它们是非协变类型。
答案 1 :(得分:5)
它正在调用most specific方法。
由于String是Object的子类,因此String比Object更“具体”。
答案 2 :(得分:5)
根据定义,null
的类型是每个其他参考类型的子类型。引用JLS 4.1:
null引用总是可以进行任何引用类型的扩展引用转换。
调用中涉及的方法签名的解析遵循所有兼容签名集中最具体签名的原则。 (JLS 15.12.2.5。选择最具体的方法)。
这意味着在您的示例中选择了String
重载。
答案 3 :(得分:2)
当两个参数在两个参数都有效的情况下进行选择时,编译器将始终选择最具体的参数作为匹配项。在这种情况下,null
是一个可以作为Object
和String
处理的文字。 String
更具体,是Object
的子类,因此编译器使用它。