为什么输出是这样的?

Che*_*tan 13 java polymorphism scjp

class Another {
    public void method(Object o) {
        System.out.println("This is in method which takes object");
    }
    public void method(String s) {
        System.out.println("This is method which takes string");
    }
}

public class NewClass {
    public static void main(String args[]) {
        Another an = new Another();
        an.method(null);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我尝试执行此操作时,我明白了

这是采用字符串的方法

作为输出.为什么不"这是采取对象的方法"?对象也可以为null,string也可以为null,为什么不调用第一个方法?

Abh*_*kar 25

根据Java语言规范,在这两种方法都可以处理提供的参数的重载方法的情况下,选择具有更具体参数的方法.由于StringObject(String延伸Object)更具体,因此void method(String)被选择和调用.


pol*_*nts 7

这与JLS中指定的完全相同:

JLS 15.12.2.5选择最具体的方法

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

A String是-a Object,但不是全部Object是-a String.因此,String更具体的Object,因此,为什么String过载被选择在上述的例子.


值得注意的是,这个确切的问题(实质上)出现在精彩的Java Puzzlers(强烈推荐)中,特别是Puzzle 46:令人困惑的构造函数的案例

Java的重载解析过程分两个阶段进行.第一阶段选择可访问和适用的所有方法或构造函数.第二阶段选择在第一阶段中选择的最具体的方法或构造函数.如果一个方法或构造函数可以接受传递给另一个的任何参数,则它的特定性不如另一个

理解这个难题的关键是对哪个方法或构造函数最具体的测试不使用实际参数:调用中出现的参数.它们仅用于确定适用的过载.一旦编译器确定哪些重载适用且可访问,它就只使用形式参数选择最具体的重载:声明中出现的参数.


我将结束有效Java第2版的引用,第41项:明智地使用重载:

确定选择哪个重载的规则非常复杂.它们在语言规范中占用了三十三页,很少有程序员理解它们的所有细微之处.

毋庸置疑,这本书也值得推荐.

也可以看看


关于显式铸造

那么如何Objectnull参数调用重载呢?

简单:转换null为类型Object.有几个场景,这是有用/必要的,这是其中之一.

如果我有超载,比如说,Integer怎么办?

然后方法调用不明确,并发生编译时错误.

JLS 15.12.2.5选择最具体的方法

可能没有方法是最具体的,因为有两种或更多种方法是最具体的.在这种情况下[...有一些例外]我们说方法调用是不明确的,并且发生编译时错误.

要解决歧义,您可以再次null(或其他表达式)转换为所需的重载类型.

也可以看看

  • 现在,如果你有另一个采用Date的方法怎么办?由于String既不是日期也不是日期是字符串,是不是指定了行为?这是一个错误吗? (3认同)

Pét*_*rök 5

在解决重载方法调用时,编译器总是会找到最窄的匹配.

顺便说一下,Java约定是为类使用大写名称,即Another.