当参数是文字空值时,如何select重载方法?

我在一个测验中遇到了这个问题,

public class MoneyCalc { public void method(Object o) { System.out.println("Object Verion"); } public void method(String s) { System.out.println("String Version"); } public static void main(String args[]) { MoneyCalc question = new MoneyCalc(); question.method(null); } } 

这个程序的输出是“string版本”。 但我不明白为什么传递null重载方法selectstring版本。 是空的一个stringvariables指向什么?

但是,当代码改变为,

 public class MoneyCalc { public void method(StringBuffer sb) { System.out.println("StringBuffer Verion"); } public void method(String s) { System.out.println("String Version"); } public static void main(String args[]) { MoneyCalc question = new MoneyCalc(); question.method(null); } } 

它给出了一个编译错误,说:“方法方法(StringBuffer)对MoneyCalctypes不明确”

是空的一个stringvariables指向什么?

空引用可以转换为任何类types的expression式。 所以在String的情况下,这是很好的:

 String x = null; 

这里select了String重载,因为Java编译器会根据JLS的15.12.2.5节select最具体的重载。 尤其是:

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

在第二种情况下,这两种方法仍然适用,但StringStringBuffer都不是比另一种更具体,因此这两种方法都没有比其他方法更具体,因此编译器错误。

此外, JLS 3.10.7还声明“null”是“空types”的字面值。 所以存在一个叫做“null”的types。

后来, JLS 4.1声明存在一个nulltypes,这是不可能声明variables的,但是只能通过null文字来使用它。 后来它说:

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

为什么编译器select将其扩展为String可能在Jon的答案中得到了解释。

您可以将一个string赋给一个null值,这样它就是有效的,而且java和大多数编程语言的顺序都是适合最接近的types,然后是对象。

为了回答标题中的问题: null既不是一个String也不是一个Object ,但是对任一个的引用都可以赋给null

我甚至惊讶这个代码编译。 我曾尝试类似的东西,我得到了一个编译器错误,说这个调用是模棱两可的。

但在这种情况下,编译器似乎select了食物链上最低的方法。 假设你想要这个方法的最小generics版本来帮助你。

我将不得不看看我是否能够在这个(貌似)完全相同的场景中发现编译器错误的例子,尽pipe…]

编辑:我明白了。 在我所做的版本中,我有两个重载的方法接受一个String和一个Integer 。 在这种情况下,没有“最具体”的参数(如在ObjectString ),所以它不能在它们之间进行select,不像你的代码。

非常酷的问题!

由于stringtypes比对象types更具体。 假设您添加一个采用Integertypes的方法。

 public void method(Integer i) { System.out.println("Integer Version"); } 

那么你会得到一个编译器错误,说这个调用是不明确的。 就像现在我们两个具有相同优先级的同样具体的方法

Java编译器给大多数派生类types分配null。

这里是了解它的例子:

 class A{ public void methodA(){ System.out.println("Hello methodA"); } } class B extends A{ public void methodB(){ System.out.println("Hello methodB"); } } class C{ public void methodC(){ System.out.println("Hello methodC"); } } public class MyTest { public static void fun(B Obj){ System.out.println("B Class."); } public static void fun(A Obj){ System.out.println("A Class."); } public static void main(String[] args) { fun(null); } } 

输出: B类。

另一方面:

 public class MyTest { public static void fun(C Obj){ System.out.println("B Class."); } public static void fun(A Obj){ System.out.println("A Class."); } public static void main(String[] args) { fun(null); } } 

结果:方法fun(C)对于MyTesttypes是不明确的

希望这会有助于更好地理解这个案例。

我也不会说。 NULL是一个不是值的状态。 看看这个链接的更多信息(这篇文章适用于SQL,但我认为它也有助于你的问题)。