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

我有以下代码片段:

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更具体。 所以,编译器决定调用这个方法。 请记住,编译器总是select最具体的方法来调用。 参见JLS的15.12.5节

如果多个成员方法都可以访问并适用于方法调用,则有必要select一个方法来为运行时方法调度提供描述符。 Java编程语言使用最具体的方法select的规则。

非正式的直觉是,如果任何由第一个方法处理的调用可以传递给另一个,而没有编译时types错误,那么其中一个方法比另一个更具体。

但是,如果你有两个参数为StringInteger ,那么你会得到一个ambiguity错误,因为编译器不能决定哪一个更具体,因为它们是非协变types。

这是调用最具体的方法。

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

  1. 根据定义, nulltypes是每个其他引用types子types 。 引用JLS 4.1:

    空引用总是可以经历扩展引用转换为任何引用types。

  2. 参与调用的方法签名的解决scheme遵循所有兼容签名集合中最具体签名的原则。 (JLS 15.12.2.5。select最具体的方法)。

综合起来,这意味着你的例子中select了String重载。

如果在两个参数之间select参数对两个参数均有效,则编译器将始终select最具体的参数作为匹配。 在这种情况下, null是可以作为ObjectString处理的文字。 String是更具体的和Object一个子类,所以编译器使用它。