在Java中选择哪个重载为空?

Mar*_*aux 52 java parameters methods invocation

如果我用Java写这行:

JOptionPane.showInputDialog(null, "Write something");
Run Code Online (Sandbox Code Playgroud)

将调用哪种方法?

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

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

Jon*_*eet 63

最具体的方法将被调用-在这种情况下,

showInputDialog(Component parent, Object message)
Run Code Online (Sandbox Code Playgroud)

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

没有深入了解细节(您可以在此处的规范中阅读),介绍给出了一个很好的总结:

如果多个成员方法都可访问并适用于方法调用,则必须选择一个为运行时方法调度提供描述符.Java编程语言使用选择最具体方法的规则.

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

  • 当定义方法`f(Integer i)`和`f(String s)`时调用`f(null)`怎么样?两者似乎都没有比另一个更具体. (6认同)

Bil*_*ard 13

在您的特定情况下,将调用更具体的方法.但是,一般情况下,某些情况下方法签名可能不明确.考虑以下:

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...");
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,编译器无法在采用Integer的方法和采用String的方法之间做出决定.当我尝试编译时,我得到了

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

  • 那讲得通.Integer和String在特异性方面都是"相等的",而Object是两者的父级,因此它更模糊.现在,如果删除了String方法,则会调用整数方法. (4认同)
  • @Thomas:没错.看起来两个不明确的类在继承树的不同分支之间的距离无关紧要,因为String直接扩展了Object,而Integer扩展了Number. (2认同)

Chs*_*y76 9

都不是.您将收到编译器错误,要求您说明要调用的方法.您可以通过显式转换第一个参数来执行此操作:

showInputDialog((Object) null, "Write something");
Run Code Online (Sandbox Code Playgroud)

要么

showInputDialog((Component) null, "Write something");
Run Code Online (Sandbox Code Playgroud)

我应该知道的更新 - 永远不要怀疑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);
  }
}
Run Code Online (Sandbox Code Playgroud)

以上将给出编译器错误.

  • @CPerkins - 是的,jcasso的注释引用了我原来的(不正确的)响应,其中我说`showInputDialog()`会抛出编译错误,而不会. (2认同)