问题

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

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 Version"。但是我无法理解为什么将null传递给重载方法会选择字符串版本。 null是一个指向什么都没有的String变量?

但是,当代码更改为,

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)对于MoneyCalc类型是不明确的"


#1 热门回答(101 赞)

null是一个String变量,指向什么?

可以将空引用转换为任何类类型的表达式。所以在String的情况下,这很好:

String x = null;

选择此处的Stringoverload是因为Java编译器选择了特定的过载,如section 15.12.2.5 of the JLS所示。尤其是:

非正式的直觉是,如果第一个方法处理的任何调用都可以传递给另一个没有编译时类型错误的调用,则一个方法比另一个方法更具体。

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


#2 热门回答(9 赞)

另外,JLS 3.10.7也声明"null"是"null类型"的文字值。因此存在一种称为"null"的类型。

后来,JLS 4.1声明存在一个无法声明变量的null类型,但是你只能通过null文字使用它。后来它说:

null引用始终可以进行任何引用类型的扩展引用转换。

为什么编译器选择将它扩展为String可能会在Jon's answer中解释。


#3 热门回答(2 赞)

你可以将astring分配给anull值,使其有效,并且java和大多数编程语言的顺序适合最接近的类型,然后适合对象。


原文链接