当参数为文本 null 值时,如何选择重载方法?

2022-08-31 10:35:41

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

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);
   }
}

该程序的输出是“字符串版本”。但是我无法理解为什么将 null 传递给重载方法会选择字符串版本。null 是指向无的字符串变量吗?

但是,当代码更改为,

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

null 是指向无的字符串变量吗?

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

String x = null;

之所以选择重载,是因为 Java 编译器根据 JLS 的 15.12.2.5 节选取了最具体的重载。特别:String

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

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


答案 2

此外,JLS 3.10.7 还声明“null”是“null 类型”的文字值。因此,存在一个名为“null”的类型。

稍后,JLS 4.1 声明存在一个 null 类型,其中不可能声明变量,但您只能通过 null 文本来使用它。后来它说:

空引用始终可以进行加宽引用转换为任何引用类型。

为什么编译器选择将其扩大到String,这很可能在Jon的答案中得到解释。