You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java继承重写场景下super方法调用子类getter的原因及实现预期输出的方法

问题解析与解决方案

这个问题其实是Java动态绑定(运行时多态)的典型表现,咱们一步步拆解来看:

为什么输出两次testB?

当你在MyClassB的printName()里调用super.printName()时,父类的printName()方法确实会执行,但核心点在于:this的指向始终是当前的MyClassB实例,并没有因为调用super就变成父类对象。

Java中实例方法的调用是动态绑定的——JVM会根据对象的实际类型(而非引用类型)来选择执行的方法。你在MyClassB里重写了getName(),所以父类printName()中的this.getName(),本质上还是调用子类MyClassB的getName()方法,自然返回testB,而不是父类的testA。

如何调整代码输出testA testB?

有两种简单的思路可以实现预期效果:

方案1:父类直接访问私有成员,绕过方法调用

修改父类MyClassA的printName(),直接输出私有成员name,而不是通过getName()方法间接获取:

public class MyClass {
    public static void main(String args[]) {
        class MyClassA {
            private String name = "testA";
            public String getName() {
                return name;
            }
            public void printName() {
                // 直接访问私有成员,避免触发动态绑定
                System.out.println(name);
            }
        }
        class MyClassB extends MyClassA {
            private String name2 = "testB";
            public String getName() {
                return name2;
            }
            public void printName() {
                super.printName();
                System.out.println(getName());
            }
        }
        MyClassA classA = new MyClassA();
        MyClassB classB = new MyClassB();
        System.out.println("Print name in A:");
        classA.printName();
        System.out.println("Print names in B:");
        classB.printName();
    }
}

修改后的运行输出:

Print name in A: testA
Print names in B: testA testB

方案2:使用不可重写的方法获取父类值

在父类中定义一个final修饰的方法(禁止子类重写),用来返回父类的name,然后父类的printName()调用这个方法:

public class MyClass {
    public static void main(String args[]) {
        class MyClassA {
            private String name = "testA";
            // final修饰,子类无法重写
            public final String getParentName() {
                return name;
            }
            public String getName() {
                return getParentName();
            }
            public void printName() {
                System.out.println(getParentName());
            }
        }
        class MyClassB extends MyClassA {
            private String name2 = "testB";
            public String getName() {
                return name2;
            }
            public void printName() {
                super.printName();
                System.out.println(getName());
            }
        }
        MyClassA classA = new MyClassA();
        MyClassB classB = new MyClassB();
        System.out.println("Print name in A:");
        classA.printName();
        System.out.println("Print names in B:");
        classB.printName();
    }
}

这个方案同样能得到预期的输出,因为getParentName()不可被重写,父类的printName()调用它时只会执行父类的实现。

内容的提问来源于stack exchange,提问作者kinglite

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 17:17:28