Java中null值会选择哪个重载方法?

54

如果我在Java中写下这行代码:

JOptionPane.showInputDialog(null, "Write something");

哪个方法将被调用?

  • showInputDialog(Component parent, Object message)
  • showInputDialog(Object message, Object initialSelectionValue)

我可以测试它。但在其他类似情况下,我想知道会发生什么。


3
这实际上是一个不错的问题,即使它是刻意构造的(你永远不会想要调用第一个,因为它与“JOptionPane.showInputDialog(“写点什么”);”完全相同。 - Powerlord
3个回答

65

将调用最具体的方法 - 在这个例子中

showInputDialog(Component parent, Object message)

这通常属于规范中的重载解析的"确定方法签名"步骤(15.12.2),特别是"选择最具体的方法"

不详细介绍(您可以在规范中阅读),引言给出了一个很好的摘要:

如果有多个成员方法既可访问又适用于方法调用,则需要选择一个方法来为运行时方法分派提供描述符。Java编程语言使用的规则是选择最具体的方法。

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


6
当定义了f(Integer i)f(String s)这两个方法时,调用f(null)会发生什么情况呢?看起来两个方法的具体性相同。 - Stephan202
@Stephan202:在Eclipse中,我得到了The method f(Integer) is ambiguous for the type ExampleClass的错误提示。这是针对静态方法的。 - Powerlord
@R. Bemrose:根据Bill的回答,这也适用于非静态方法。感谢测试! - Stephan202

14
在您的特定情况下,将调用更具体的方法。然而,一般情况下,方法签名可能存在歧义。请考虑以下内容:
public class Main {

    public static void main(String[] args) {
        Main m = new Main();
        m.testNullArgument(null);
    }

    private void testNullArgument( Object o )
    {
        System.out.println("An Object was passed...");
    }

    private void testNullArgument( Integer i )
    {
        System.out.println("An Integer was passed...");
    }

    private void testNullArgument( String s )
    {
        System.out.println("A String was passed...");
    }
}

在这种情况下,编译器无法决定使用需要一个整数的方法还是需要一个字符串的方法。 当我尝试编译时,我会得到以下错误:

reference to testNullArgument is ambiguous, both method testNullArgument(java.lang.Integer) in testnullargument.Main and method testNullArgument(java.lang.String) in testnullargument.Main match

4
这很有道理。在特定性方面,整数和字符串都是“相等的”,而对象是两者的父类,因此更加模糊。现在,如果您删除了字符串方法,则将调用整数方法。 - Thomas Owens
2
@Thomas:没错。看起来这并不影响两个模糊类在继承树的不同分支上的深度,因为String直接扩展Object,而Integer扩展Number。 - Bill the Lizard

9

都不对。你会收到一个编译器错误,要求你澄清你想要调用哪个方法。你可以通过明确转换第一个参数来这样做:

showInputDialog((Object) null, "Write something");

或者

showInputDialog((Component) null, "Write something");

更新 我应该知道 - 永远不要怀疑Jon Skeet。我上面提到的问题只会在无法确定哪种方法更具体时发生。这是一个测试案例:

public class Test {

  public void doSomething(String arg1, Object arg2) {
    System.out.println("String, Object");
  }

  public void doSomething(Object arg1, String arg2) {
    System.out.println("Object, String");
  }

  public static void main(String[] args) {
    Test test = new Test();
    test.doSomething(null, null);
  }
}

以上代码将会导致编译错误。

@jcasso - 我在“doSomething”行上看到编译器错误,提示“方法doSomething(String,Object)对于类型不明确”。 - CPerkins
2
@CPerkins - 是的,jcasso的评论是指我的原始(不正确)回答,我说showInputDialog()会抛出编译器错误,但实际上并不会。 - ChssPly76

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接