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

Java中如何调用被子类重写的抽象父类方法?

问题:如何调用抽象父类中被子类重写的方法?

我是编程新手,学习Java时遇到一个问题:我想在测试类中调用抽象父类里实现、但被子类重写的方法。具体来说,我用子类TestingImpl3333的构造器创建了抽象父类TestingImpl1111的对象,想调用TestingImpl1111的m1()方法,以及TestingImpl2222的m2()方法,但不管是不是强制类型转换,调用的始终是子类重写后的方法,得不到期望的输出。

我的代码

package PolymorphismAndAbstraction.Example1.Example2;

interface ITesting1111
{
    void m1();
    void m2();
    void m3();
}
abstract class TestingImpl1111 implements ITesting1111
{
    public void m1()
    {
        System.out.println("testing method from interface in class 1111");
    }
}
abstract class TestingImpl2222 extends TestingImpl1111
{
    public void m1() 
    {
        System.out.println("testing method m1 from interface in class 2222 which was implemented in class 1111 as well.");      
    }   
    public void m2() 
    {
        System.out.println("testing method from interface in class 2222");      
    }   
}
 class TestingImpl3333 extends TestingImpl2222
{
        public void m2() 
        {
            System.out.println("testing method m2 from interface in class 3333 which was implemented in class 2222 as well.");      
        }
    public void m3()
    {
        System.out.println("testing method from interface in class 3333");      
    }
}

public class Test1234 
{
    public static void main(String[] args) 
    {   
        TestingImpl1111 obj = new TestingImpl3333();        
        
        ((TestingImpl1111)obj).m1();
        obj.m1();
        ((TestingImpl2222)obj).m2();
        obj.m2();       
        obj.m3();       
    }
}

当前输出

testing method m1 from interface in class 2222 which was implemented in class 1111 as well.
testing method m1 from interface in class 2222 which was implemented in class 1111 as well.
testing method m2 from interface in class 3333 which was implemented in class 2222 as well.
testing method m2 from interface in class 3333 which was implemented in class 2222 as well.
testing method from interface in class 3333

期望输出

testing method m1 from interface in class 2222 which was implemented in class 1111 as well.
testing method from interface in class 1111
testing method m2 from interface in class 3333 which was implemented in class 2222 as well.
testing method from interface in class 2222
testing method from interface in class 3333

问题原因与解决方法

核心原因

你遇到的问题本质是Java的多态机制:当父类引用指向子类对象时,调用被重写的方法时,JVM会根据对象的实际运行时类型(也就是子类)来执行对应的方法。强制类型转换只是改变了编译阶段的类型检查逻辑,并不会改变对象本身的实际类型,所以无论怎么转换,最终执行的都是子类重写后的方法。

解决方法

要调用父类的重写方法,你需要通过类内部的方法来触发父类实现,有两种常用方式:

方式1:在子类中添加调用父类方法的入口

在对应的子类中新增方法,通过super关键字调用父类的实现:

  • 在TestingImpl2222中添加调用TestingImpl1111的m1()的方法:
public void callParentM1() {
    super.m1(); // 调用父类TestingImpl1111的m1实现
}
  • 在TestingImpl3333中添加调用TestingImpl2222的m2()的方法:
public void callParentM2() {
    super.m2(); // 调用父类TestingImpl2222的m2实现
}

修改后的测试类代码:

public class Test1234 
{
    public static void main(String[] args) 
    {   
        TestingImpl1111 obj = new TestingImpl3333();        
        
        obj.m1(); // 执行TestingImpl2222的m1
        ((TestingImpl2222)obj).callParentM1(); // 执行TestingImpl1111的m1
        obj.m2(); // 执行TestingImpl3333的m2
        ((TestingImpl3333)obj).callParentM2(); // 执行TestingImpl2222的m2
        obj.m3();       
    }
}

方式2:将父类方法逻辑提取为非重写方法

在父类中把原方法的核心逻辑提取成一个final修饰的方法(避免被子类重写),这样可以直接调用这个方法来获取父类的逻辑:

  • 在TestingImpl1111中修改:
public void m1() {
    m1Impl();
}

// final修饰,子类无法重写
public final void m1Impl() {
    System.out.println("testing method from interface in class 1111");
}
  • 在TestingImpl2222中修改:
public void m2() {
    m2Impl();
}

public final void m2Impl() {
    System.out.println("testing method from interface in class 2222");
}

测试类中直接调用这些final方法即可:

public class Test1234 
{
    public static void main(String[] args) 
    {   
        TestingImpl1111 obj = new TestingImpl3333();        
        
        obj.m1(); // 执行TestingImpl2222的m1
        ((TestingImpl1111)obj).m1Impl(); // 执行TestingImpl1111的m1逻辑
        obj.m2(); // 执行TestingImpl3333的m2
        ((TestingImpl2222)obj).m2Impl(); // 执行TestingImpl2222的m2逻辑
        obj.m3();       
    }
}

这两种方式都能实现你的期望输出,方式2的扩展性更好,后续如果有更多子类继承,不需要重复添加调用方法。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 05:27:38