方法重载中奇怪的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错误,那么其中一个方法比另一个更具体。
但是,如果你有两个参数为String
和Integer
,那么你会得到一个ambiguity
错误,因为编译器不能决定哪一个更具体,因为它们是非协变types。
这是调用最具体的方法。
由于String是Object的子类,因此String比Object更“特定”。
-
根据定义,
null
的types是每个其他引用types的子types 。 引用JLS 4.1:空引用总是可以经历扩展引用转换为任何引用types。
-
参与调用的方法签名的解决scheme遵循所有兼容签名集合中最具体签名的原则。 (JLS 15.12.2.5。select最具体的方法)。
综合起来,这意味着你的例子中select了String
重载。
如果在两个参数之间select参数对两个参数均有效,则编译器将始终select最具体的参数作为匹配。 在这种情况下, null
是可以作为Object
和String
处理的文字。 String
是更具体的和Object
一个子类,所以编译器使用它。