当参数是文字空值时,如何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错误,那么其中一个方法比另一个更具体。
在第二种情况下,这两种方法仍然适用,但String
和StringBuffer
都不是比另一种更具体,因此这两种方法都没有比其他方法更具体,因此编译器错误。
此外, 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
。 在这种情况下,没有“最具体”的参数(如在Object
和String
),所以它不能在它们之间进行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,但我认为它也有助于你的问题)。