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

A superclass method is called instead of the subclass method

让我们看一下这段代码:

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 调用 super class 而不是,我该怎么做才能让它调用 subclass 中的方法?

SubClass#foo() 不会覆盖 ParentClass#foo() 因为它没有相同的形式参数。一个拿Object,一个拿String。因此,运行时的多态性不适用,也不会导致子类方法执行。来自 Java Language Specification:

An instance method m<sub>C</sub> declared in or inherited by class C, overrides from C another method m<sub>A</sub> declared in class A, iff all of the following are true:

  • A is a superclass of C.

  • C does not inherit m<sub>A</sub>.

  • The signature of m<sub>C</sub> is a subsignature (§8.4.2) of the signature of m<sub>A</sub>.

...

并且this section定义方法签名:

Two methods or constructors, M and N, have the same signature if they have the same name, the same type parameters (if any) (§8.4.4), and, after adapting the formal parameter types of N to the the type parameters of M, the same formal parameter types.

The signature of a method m<sub>1</sub> is a subsignature of the signature of a method m<sub>2</sub> if either:

  • m<sub>2</sub> has the same signature as m<sub>1</sub>, or

  • the signature of m1 is the same as the erasure (§4.6) of the signature of m<sub>2</sub>.

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

由于子class没有覆盖这个方法(它没有相同的参数类型),父class的foo方法是被执行的在运行时。

字符串是 java 中的对象,如前所述,它不会被覆盖,但是当您传递一个字符串时,它将 运行 第一个可以作为参数的可用方法,在这种情况下它是 super -class的方法。