调用超类方法而不是子类方法

我们来看看这段代码:

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不inheritancem A

  • m C的签名是m A签名的子签名(第8.4.2节)。

本节定义了方法签名:

两个方法或构造函数M和N具有相同的签名,如果它们具有相同的名称,相同的类型参数(如果有的话)(第8.4.4节),并且在将forms参数类型N调整为类型参数之后M,相同的forms参数类型。

方法m 1的签名是方法m 2的签名的子签名,如果:

  • m 2m 1具有相同的特征,或者

  • m1的签名与m 2签名的擦除(§4.6)相同。

父类没有带有签名public void foo(String s) 。 因此,在编译时,编译器只能选择public void foo(Object o)方法来执行p.foo("hello")

由于子类不重写此方法(它没有相同的参数类型),因此父类的foo方法是在运行时执行的方法。

字符串是java中的对象,因为它没有被覆盖,但是当你传递一个字符串时,它将运行第一个可用于参数的方法,在这种情况下它是超类的方法。