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

时间:2012-10-23 14:42:04

标签: java overloading

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

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"

类型是不明确的

7 个答案:

答案 0 :(得分:101)

  

null是一个指向什么都没有的String变量吗?

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

String x = null;

选择String重载是因为Java编译器根据section 15.12.2.5 of the JLS选择最具体的重载。特别是:

  

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

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

答案 1 :(得分:9)

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

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

  

null引用总是可以进行扩展引用转换   任何参考类型。

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

答案 2 :(得分:2)

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

答案 3 :(得分:2)

要回答标题中的问题:null既不是String也不是Object,但可以将对其中任何一个的引用分配给null

我真的很惊讶这个代码甚至编译。我之前尝试过类似的东西,但是我收到编译错误,说这个调用很模糊。

但是,在这种情况下,似乎编译器选择的是食物链中最低的方法。假设您需要方法的最不通用版本以帮助您。

我将不得不看看我是否可以在这个(貌似)完全相同的场景中挖掘出我遇到编译器错误的例子,但是......]

编辑:我明白了。在我制作的版本中,我有两个重载方法接受StringInteger。在这种情况下,没有“最具体”参数(如ObjectString中所示),因此它不能在它们之间进行选择,这与您的代码不同。

很酷的问题!

答案 4 :(得分:0)

As String类型比Object类型更具体。我们假设您再添加一个采用Integer类型的方法。

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

然后你会收到编译错误,说这个调用是不明确的。现在我们有两个具有相同优先权的同样具体的方法。

答案 5 :(得分:0)

Java编译器为大多数派生类类型赋予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)对于MyTest类型

是不明确的

希望有助于更好地理解这种情况。

答案 6 :(得分:-1)

我不会说。 NULL是状态而不是值。查看此link以获取更多相关信息(该文章适用于SQL,但我认为它也有助于解决您的问题。)