调用超类方法而不是子类方法
我们来看看这段代码:
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会调用超类,我该怎么做才能让它调用子类中的方法?
SubClass#foo()
不会覆盖ParentClass#foo()
因为它没有相同的forms参数。 一个接受Object
,另一个接受String
。 因此,不会应用运行时的多态,也不会导致子类方法执行。 从Java语言规范 :
在类
m C
声明或inheritance的实例方法m C
,从C类中声明的另一个方法m A
覆盖 ,iff以下所有条件都为真:
A是C的超类。
C不inheritance
m A
m C
的签名是m A
签名的子签名(第8.4.2节)。…
本节定义了方法签名:
两个方法或构造函数M和N具有相同的签名,如果它们具有相同的名称,相同的类型参数(如果有的话)(第8.4.4节),并且在将forms参数类型N调整为类型参数之后M,相同的forms参数类型。
方法
m 1
的签名是方法m 2
的签名的子签名,如果:
m 2
与m 1
具有相同的特征,或者
m1
的签名与m 2
签名的擦除(§4.6)相同。
父类没有带有签名public void foo(String s)
。 因此,在编译时,编译器只能选择public void foo(Object o)
方法来执行p.foo("hello")
。
由于子类不重写此方法(它没有相同的参数类型),因此父类的foo
方法是在运行时执行的方法。
字符串是java中的对象,因为它没有被覆盖,但是当你传递一个字符串时,它将运行第一个可用于参数的方法,在这种情况下它是超类的方法。