为什么调用以父class为参数的方法,而不调用以子class为参数的方法?

Why the method that gets the Father class as a parameter is called and not the method that gets the child class as a parameter?

我有一个名为 A 的 class 和一个扩展 A 的名为 B 的 class。 在使用一些方法来理解多态行为时,我 运行 陷入了一个奇怪的境地。

public class Main {
    public static void main(String[] args){
        B b = new B();
        A a = b;
        b.f1(a);
    }
}

public class A {
.
.
.
    public void f1(A a){
        if(a instanceof B)
            f1((B)a);
        else
            System.out.println("Nothing");
    }
.
.
.
}

public class B extends A {
.
.
.
    public void f1(B b){
        System.out.println("B::f1(B)");
    }
.
.
.
}

我希望 class A 中的 f1 首先被调用(因为 a 是 A 类型),这实际上发生了。然后我期待 f1((B)a);被调用,因为 a 是 B 的一个实例。到现在为止一切都按预期进行。但是,我认为下一个将被调用的方法是 class B 中的 f1(B) 。相反, class A 中的 f1(A) 被反复调用导致堆栈溢出异常。为什么 class B 中的 f1(B) 没有被调用? B 的一个实例是调用者,参数被强制转换为 B 类型。

f1(A a)是classA的实例方法。它不知道 A 的子 classes 的方法。因此,它不能调用 void f1(B b) of class B。因此,f1((B)a)再次执行void f1(A a)

如果你想调用 f1(B b),你必须在 class 的实例变量上调用 f1 B:

public void f1(A a){
    if(a instanceof B) {
        B b = (B)a;
        b.f1(b);
    } else {
        System.out.println("Nothing");
    }
}

你的 class A 不知道 class B 存在于某处并且具有 B.f1(B b) 函数。实际上 f1(A a) 和 f1(B b) 是两个不同的函数。您可能想要实现的目标,应该以不同的方式完成:

public class A {
//...
    public void f1(A a) {
         System.out.println("Nothing");
    }
//...
}

public class B {
//...
    public void f1(B a) {
        // this is different function, because of another parameters
    }

    public void f1(A a) {
        if(a instanceof B)
            f1((B)a);
        else
            super.f1(a);
    }
//...
}

代码必须按如下方式转换方法的调用者:

public class A {

    public void f1(A a){
        if(a instanceof B)
            ((B) this).f1(a);
        else
            System.out.println("Nothing");
    }
}

在您的代码中,您只转换了参数。这样做会导致递归调用相同 class 的相同方法。

如果您改为转换调用者,您会通知 JVM 您想要调用子方法class,这样您就可以立即退出该方法。

重要 请注意,根据参数对调用者调用强制转换会生成 class 强制转换异常,例如在以下上下文中:

    B b = new B();
    A a = new A();
    a.f1(b);

不能确定接收 B 参数的方法 f1 是在 B 对象上调用的