我们来看看这段代码:
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");
}
}
我希望这打印出“Child”,但结果是“Parent”。为什么java会调用超类,我该怎么做才能让它调用子类中的方法?
答案 0 :(得分:2)
SubClass#foo()
不会覆盖ParentClass#foo()
,因为它没有相同的形式参数。一个需要Object
,另一个需要String
。因此,不会应用运行时的多态,也不会导致子类方法执行。来自Java Language Specification:
在类C中声明或继承的实例方法
mC
,覆盖来自C类A中声明的另一个方法mA
,iff以下所有条件都为真: / p>
A是C的超类。
C不会继承
mA
。
mC
的签名是mA
签名的子签名(第8.4.2节)。...
this section定义了方法签名:
两个方法或构造函数M和N具有相同的签名,如果它们具有相同的名称,相同的类型参数(如果有的话)(第8.4.4节),并且在调整之后形式参数类型N为M的类型参数,形式参数类型相同。
方法
m1
的签名是方法m2
签名的子签名,如果是:
m2
与m1
具有相同的签名,或
m1
的签名与m2
签名的删除(§4.6)相同。
答案 1 :(得分:1)
父类没有带签名public void foo(String s)
的方法。因此,在编译时,编译器只能选择public void foo(Object o)
方法来执行p.foo("hello")
。
由于子类没有覆盖此方法(它没有相同的参数类型),因此父类的foo
方法是在运行时执行的方法。
答案 2 :(得分:0)
字符串是java中的对象,因为它没有被覆盖,但是当你传递一个字符串时,它将运行第一个可用于该参数的方法,在这种情况下它是超类的方法。