【问题标题】:A superclass method is called instead of the subclass method调用超类方法而不是子类方法
【发布时间】:2015-07-05 12:56:38
【问题描述】:
让我们看看这段代码:
public class ParentClass {
public void foo(Object o) {
System.out.println("Parent");
}
}
public class SubClass extends ParentClass {
public void foo(String s) {
System.out.println("Child");
}
public static void main(String args[]) {
ParentClass p = new SubClass();
p.foo("hello");
}
}
我希望这会打印出“孩子”,但结果是“父母”。 java为什么要调用超类,我该怎么做才能让它调用子类中的方法?
【问题讨论】:
标签:
java
inheritance
polymorphism
overriding
【解决方案1】:
SubClass#foo() 不会覆盖ParentClass#foo(),因为它没有相同的形参。一个接受Object,另一个接受String。因此不应用运行时的多态性并且不会导致子类方法执行。来自Java Language Specification:
在 C 类中声明或继承的实例方法 m<sub>C</sub>,覆盖 C 中在 A 类中声明的另一个方法 m<sub>A</sub>,如果满足以下所有条件:
...
而this section 定义了方法签名:
两个方法或构造函数,M 和 N,如果它们具有相同的名称、相同的类型参数(如果有)(第 8.4.4 节),并且在适应N的形参类型与M的形参类型相同。
m<sub>1</sub> 方法的签名是m<sub>2</sub> 方法签名的子签名,如果:
【解决方案2】:
父类没有签名为public void foo(String s)的方法。因此,在编译时,编译器只能选择public void foo(Object o)方法来执行p.foo("hello")。
由于子类没有重写这个方法(它没有相同的参数类型),父类的foo方法是在运行时执行的。
【解决方案3】:
字符串是java中的对象,正如前面所说的,它没有被覆盖,但是当你传递一个字符串时,它将运行第一个可以作为参数的可用方法,在这种情况下它是超类的方法。