方法重载中的奇怪Java null行为

时间:2013-02-09 15:14:12

标签: java null overloading

我有以下代码段:

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)

4 个答案:

答案 0 :(得分:21)

  

为什么程序会调用foo(String x)而不是foo(Object x)

这是因为String类从Object延伸,因此更具体到Object。因此,编译器决定调用该方法。请记住,编译器总是选择最具体的方法来调用。见Section 15.12.5 of JLS

  

如果多个成员方法都可访问且适用于a   方法调用,有必要选择一个提供   运行时方法调度的描述符。 Java编程   language使用选择最具体方法的规则。

     

非正式的直觉是一种方法更具体   如果可以传递第一个方法处理的任何调用,则为另一个   没有编译时类型错误的另一个。

但是,如果您有两个带参数的方法 - StringInteger,则ambiguity会出现null错误,因为编译器无法确定哪个是{{1}}更具体,因为它们是非协变类型。

答案 1 :(得分:5)

它正在调用most specific方法。

由于String是Object的子类,因此String比Object更“具体”。

答案 2 :(得分:5)

  1. 根据定义,null的类型是每个其他参考类型的子类型。引用JLS 4.1:

      

    null引用总是可以进行任何引用类型的扩展引用转换。

  2. 调用中涉及的方法签名的解析遵循所有兼容签名集中最具体签名的原则。 (JLS 15.12.2.5。选择最具体的方法)。

  3. 这意味着在您的示例中选择了String重载。

答案 3 :(得分:2)

当两个参数在两个参数都有效的情况下进行选择时,编译器将始终选择最具体的参数作为匹配项。在这种情况下,null是一个可以作为ObjectString处理的文字。 String更具体,是Object的子类,因此编译器使用它。