Java:调用调用被覆盖方法的超级方法

2022-08-31 09:52:59
public class SuperClass
{
    public void method1()
    {
        System.out.println("superclass method1");
        this.method2();
    }

    public void method2()
    {
        System.out.println("superclass method2");
    }

}

public class SubClass extends SuperClass
{
    @Override
    public void method1()
    {
        System.out.println("subclass method1");
        super.method1();
    }

    @Override
    public void method2()
    {
        System.out.println("subclass method2");
    }
}



public class Demo 
{
    public static void main(String[] args) 
    {
        SubClass mSubClass = new SubClass();
        mSubClass.method1();
    }
}

我的预期输出:

子类方法1
超类方法1
超类方法2

实际输出:

子类方法1
超类方法1
子类方法2

我知道从技术上讲,我已经覆盖了一个公共方法,但我认为,因为我在调用超级,超级内的任何调用都会留在超级中,这并没有发生。关于我如何实现它的任何想法?


答案 1

关键字不会“坚持”。每个方法调用都是单独处理的,因此,即使您通过调用 进行,也不会影响将来可能进行的任何其他方法调用。superSuperClass.method1()super

这意味着没有直接的方法来调用而不去,除非你正在使用的实际实例。SuperClass.method2()SuperClass.method1()SubClass.method2()SuperClass

你甚至不能使用Refprection达到预期的效果(参见java.lang.reflect.Method.invoke(Object, Object...)的文档)。

[编辑]似乎仍然存在一些混乱。让我尝试一个不同的解释。

调用 时,您实际上调用了 。Java 只是允许您省略 .在问题的示例中,的类型为 。foo()this.foo()thisthisSubClass

所以当Java执行中的代码时,它最终会到达SuperClass.method1()this.method2();

使用 不会更改 所指向的实例。因此,调用转到,因为类型为 。superthisSubClass.method2()thisSubClass

也许当你想象Java作为隐藏的第一个参数传递时,更容易理解:this

public class SuperClass
{
    public void method1(SuperClass this)
    {
        System.out.println("superclass method1");
        this.method2(this); // <--- this == mSubClass
    }

    public void method2(SuperClass this)
    {
        System.out.println("superclass method2");
    }

}

public class SubClass extends SuperClass
{
    @Override
    public void method1(SubClass this)
    {
        System.out.println("subclass method1");
        super.method1(this);
    }

    @Override
    public void method2(SubClass this)
    {
        System.out.println("subclass method2");
    }
}



public class Demo 
{
    public static void main(String[] args) 
    {
        SubClass mSubClass = new SubClass();
        mSubClass.method1(mSubClass);
    }
}

如果您遵循调用堆栈,您可以看到永远不会改变,它始终是在 中创建的实例。thismain()


答案 2

只能在重写方法(或重写类的其他方法)中访问重写的方法。

所以:要么不要覆盖,要么在被覆盖的版本内调用。method2()super.method2()


推荐