【问题标题】:Strange Java null behavior in Method Overloading [duplicate]方法重载中奇怪的 Java null 行为
【发布时间】:2013-01-25 05:12:26
【问题描述】:
我有以下代码sn-p:
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)?
【问题讨论】:
标签:
java
null
overloading
【解决方案1】:
为什么程序调用foo(String x)而不是foo(Object x)
这是因为String 类从Object 扩展而来,因此更具体到Object。因此,编译器决定调用该方法。请记住,编译器总是选择最具体的方法来调用。见Section 15.12.5 of JLS
如果多个成员方法既可访问又适用于
方法调用,需要选择一个来提供
运行时方法分派的描述符。 Java 编程
语言使用选择最具体方法的规则。
非正式的直觉是一种方法比
如果可以传递第一个方法处理的任何调用,则另一个
在没有编译时类型错误的情况下转到另一个。
但是,如果您有两个带有参数的方法 - String 和 Integer,那么对于 null,您将收到 ambiguity 错误,因为编译器无法确定哪一个更具体,因为它们不是协变类型。
【解决方案2】:
-
null 的类型根据定义是所有其他引用类型的子类型。引用 JLS 4.1:
空引用总是可以进行扩展引用转换为任何引用类型。
-
调用中涉及的方法签名的解析遵循所有兼容签名集合中最具体的签名的原则。 (JLS 15.12.2.5。选择最具体的方法)。
综合起来,这意味着在您的示例中选择了 String 重载。
【解决方案3】:
它正在调用most specific 方法。
由于 String 是 Object 的子类,因此 String 比 Object“更具体”。
【解决方案4】:
当在参数对两个参数都有效的两种方法之间进行选择时,编译器将始终选择最具体的参数作为匹配项。在这种情况下,null 是一个可以作为Object 和String 处理的文字。 String 更具体,是Object 的子类,因此编译器使用它。