在Java中给出同一个类的两个方法:
public void doSomething( Person person );
public void doSomething( Employee employee );
,其中
Employee extends Person
如果我打电话:
doSomething( employee )
我发现doSomething( Person )
被调用了。
我原本期望调用最接近匹配合约的重载,而不是最抽象的(这是我发现的)
有人可以解释原因吗?
答案 0 :(得分:13)
使用了最具体的适用重载 - 但是根据employee
变量的编译时类型, compile -time确定了该重载。
换句话说:
Employee employee = new Employee();
doSomething(employee); // Calls doSomething(Employee)
但:
Person employee = new Employee();
doSomething(employee); // Calls doSomething(Person)
请注意,这与覆盖不同,它是目标对象的执行时间类型,这很重要。
答案 1 :(得分:3)
employee
是如何宣布的?如果它被声明为Person employee = new Employee();
,那么doSomething(Person)
确实是最接近的匹配重载。
与覆盖不同,重载是在编译时确定的。因此,即使employee
的运行时类型为Employee
,也已选择执行Person
重载。
当调用方法(§15.12)时,在编译时使用实际参数的数量(以及任何显式类型参数)和参数的编译时类型来确定方法的签名。将被调用(§15.12.2)。如果要调用的方法是实例方法,则将在运行时使用动态方法查找(§15.12.4)确定要调用的实际方法。
答案 2 :(得分:0)
在调用重载时,将调用具有最接近匹配签名的方法。我怀疑您的employee
是Person
变量。因此,在方法调用中,引用类型employee
会导致doSomething(Person person)
被选中。
答案 3 :(得分:0)
方法选择在编译时而不是运行时完成,所以如果你有
Person employee = new Employee();
doSomething(employee);
这将调用doSomething(Person),因为声明的类型是Person,而不管实例是否也是Employee。