java – 为什么调用将父类作为参数的方法调用,而不是将子类作为参数获取的方法?

我有一个名为A的类,以及一个名为B的类,它扩展了A.
玩一些方法来理解多态行为,我遇到了一个奇怪的情况.

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)");
    }
.
.
.
}

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

解决方法

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

如果要调用f1(B b),则必须在类B的实例变量上调用f1:

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

相关文章

HashMap是Java中最常用的集合类框架,也是Java语言中非常典型...
在EffectiveJava中的第 36条中建议 用 EnumSet 替代位字段,...
介绍 注解是JDK1.5版本开始引入的一个特性,用于对代码进行说...
介绍 LinkedList同时实现了List接口和Deque接口,也就是说它...
介绍 TreeSet和TreeMap在Java里有着相同的实现,前者仅仅是对...
HashMap为什么线程不安全 put的不安全 由于多线程对HashMap进...