在 Java 中,哪个重载会被选为 null?

Posted

技术标签:

【中文标题】在 Java 中,哪个重载会被选为 null?【英文标题】:Which overload will get selected for null in Java? 【发布时间】:2010-12-05 10:54:23 【问题描述】:

如果我用 Java 写这行代码:

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

会调用哪个方法?

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

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

【问题讨论】:

这实际上是一个好问题,即使它是人为的(你永远不想调用第一个,因为它与 JOptionPane.showInputDialog("Write something"); 相同 【参考方案1】:

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

showInputDialog(Component parent, Object message)

这通常属于规范 (15.12.2) 中重载解析的"Determine Method Signature" 步骤,尤其是"Choosing the Most Specific Method"。

没有深入细节(您可以在此处阅读规范中的内容),引言给出了很好的总结:

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

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

【讨论】:

在定义了f(Integer i)f(String s) 方法时调用f(null) 怎么样?两者似乎都不比另一个更具体。 @Stephan202:在 Eclipse 中,我得到 The method f(Integer) is ambiguous for the type ExampleClass 这是使用静态方法 @R. Bemrose:从比尔的回答来看,这也适用于非静态方法。感谢您的测试!【参考方案2】:

在您的特定情况下,将调用更具体的方法。但是,一般来说,在某些情况下,方法签名可能会模棱两可。考虑以下几点:

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...");
    

在这种情况下,编译器无法在采用 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

【讨论】:

这是有道理的。 Integer 和 String 在特异性方面都是“相等的”,而 Object 是两者的父级,因此更加模糊。现在,如果您删除 String 方法,则会调用 Integer 方法。 @Thomas:没错。看起来这两个模棱两可的类在继承树的不同分支上的位置也无关紧要,因为 String 直接扩展 Object,而 Integer 扩展 Number。【参考方案3】:

也没有。您将收到一个编译器错误,要求您澄清要调用的方法。您可以通过显式转换第一个参数来做到这一点:

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 - 是的,jcasso 的评论指的是我原来的(不正确的)回复,我说showInputDialog() 会抛出编译器错误,而它不会。

以上是关于在 Java 中,哪个重载会被选为 null?的主要内容,如果未能解决你的问题,请参考以下文章

Java中调用了哪个重载方法

java中重载,继承,重写和多态的区别

Java 中方法的重载

关于JAVA重载的问题~!

Java中重载和重写

Java中重载和重写的区别