带有null参数的Java方法调度

时间:2008-12-18 08:28:37

标签: java null method-dispatch

为什么我(显然)会直接将null作为参数传递,或传递Object我分配的 null

Object testVal = null;
test.foo(testVal);    // dispatched to foo(Object)
// test.foo(null);    // compilation problem -> "The method foo(String) is ambiguous"   

public void foo(String arg) { // More-specific
    System.out.println("foo(String)");
}

public void foo(Object arg) { // Generic
    System.out.println("foo(Object)");
}

换句话说,为什么foo(...)的(已注释掉的)第二次调用未发送到foo(Object)

更新:我使用的是Java 1.6。我可以毫无问题地编译Hemal的代码,但我仍然无法编译。我看到的唯一区别是,Hemal的方法是静态的,而我的方法则不是。但我真的不明白为什么这应该有所作为......?

更新2:已解决。我的班级中有另一个方法foo(Runnable),因此调度员无法明确地选择最具体的方法。 (请参阅我在Hemal的第二个答案中的评论。)感谢大家的帮助。

4 个答案:

答案 0 :(得分:24)

您使用的是哪个版本的Java?使用1.6.0_11代码(粘贴在下面)编译并运行。

我确信foo(testVal)转到foo(Object)的原因很明显。

foo(null)转到foo(String)的原因有点复杂。常量null的类型为nulltype,它是所有类型的子类型。因此,nulltype扩展了String,扩展了Object

当您调用foo(null)时,编译器会查找具有最特定类型的重载方法。由于String更具体,因此Object是被调用的方法。

如果你有另一个特定于String的重载,比如foo(Integer)那么你会得到一个模糊的重载错误。

class NullType {

  public static final void main(final String[] args) {
    foo();
  }

  static void foo()
  {
    Object testVal = null;
    foo(testVal);    // dispatched to foo(Object)
    foo(null);    // compilation problem -> "The method foo(String) is ambiguous"   
  }

  public static void foo(String arg) { // More-specific
    System.out.println("foo(String)");
  }

  public static void foo(Object arg) { // Generic
    System.out.println("foo(Object)");
  }

}

答案 1 :(得分:2)

因为第二个带有null的注释掉调用对编译器来说是不明确的。文字null可以是字符串或对象。而指定的值具有明确的类型。你需要转换null,例如test.foo((String)null)消除歧义。

答案 2 :(得分:1)

有没有人试过这个例子???

用1.6.0 foo(null)调度到最适用的方法foo(String)...

如果你添加一个新方法说foo(整数),编译器就无法选择最具体的适用方法并显示错误。

-Patrick

答案 3 :(得分:1)

很抱歉使用答案进行评论,但我需要发布不适合评论的代码。

@Yang,我也能编译并运行以下内容。你可以发布一个完整的代码,用一行注释编译,如果我取消注释该行,它将无法编译?

class NullType {

  public static final void main(final String[] args) {
    foo();
    new Test().bar(new Test());
  }

  static void foo()
  {
    Object testVal = null;
    foo(testVal);    // dispatched to foo(Object)
    // foo(null);    // compilation problem -> "The method foo(String) is ambiguous"   
  }

  public static void foo(String arg) { // More-specific
    System.out.println("foo(String)");
  }

  public static void foo(Integer arg) { // More-specific
    System.out.println("foo(Integer)");
  }

  public static void foo(Object arg) { // Generic
    System.out.println("foo(Object)");
  }


}


class Test
{
  void bar(Test test)
  {
    Object testVal = null;
    test.foo(testVal);    // dispatched to foo(Object)
    test.foo(null);    // compilation problem -> "The method foo(String) is ambiguous"   
  }

  public void foo(String arg) { // More-specific
    System.out.println("foo(String)");
  }

  public void foo(Object arg) { // Generic
    System.out.println("foo(Object)");
  }
}