Java:为什么从未调用过这个函数?

时间:2012-10-24 12:54:56

标签: java class inheritance compilation

package main;

class F {
    void f() {
        System.out.print("F.f() ");
        this.g();
    }

    void g() {
        System.out.print("F.g() ");
    }
}

class Fbis extends F {
    void f() {
        System.out.print("Fbis.f() ");
        this.g();
    }

    void g() {
        System.out.print("Fbis.g() ");
        super.f();
    }
}

public class Main {
    public static void main(String[] args) {
        F f = new Fbis();
        ((F) f).f();
    }
}

嗨,我试图理解为什么永远不会调用F类中的g()函数。 此代码编译并运行,但会导致无限循环显示:

Fbis.f() Fbis.g() F.f() Fbis.g() F.f() Fbis.g() F.f() Fbis.g() F.f() Fbis.g() F.f() Fbis.g() F.f() Fbis.g() F.f() Fbis.g() F.f() ...

所以会发生什么,是Fbis.f被调用,调用Fbis.g,调用F.f但不是调用F.gF.f调用{{ 1}}。

6 个答案:

答案 0 :(得分:9)

基本上,这就是继承的工作原理。 Fbis类会覆盖g()方法,因此Fbis调用g()的任何实例都会运行Fbis类中的代码,即使这是从内部调用的F类本身。

这通常是理想的行为。例如,假设一个delete()方法。在父类中,当应用程序删除对象时,这会进行一些清理。在儿童班中,它为这个孩子做了额外的清理工作。您希望在调用delete()时进行额外的清理,即使这是来自父类。

答案 1 :(得分:0)

   F.f但是F.f不是叫F.g,而是叫Fbis.g。

您的代码说

void f(){System.out.print("F.f() ");this.g();}

这意味着F.f()应该调用此类实现的类的g();

如果您希望Fbis.g致电F.g,您可以写

void g(){System.out.print("Fbis.g() "); super.g();}

答案 2 :(得分:0)

当您覆盖某个方法时,无论您从哪里调用它,都会始终使用被覆盖的版本。

当您在基类中执行this.g(),并且当前对象属于子类时,您在子类中调用g()

如果基类中有从基类调用的任何方法,并且您不希望它们被派生类替换,那么您应该将该方法设置为private和final。

答案 3 :(得分:0)

您的Fbis课程会覆盖方法g()。如果您创建Fbis的新对象,则g中唯一的方法是Fbis中定义的方法。即使你从一个继承的方法中调用它,它仍然是唯一的一个。否则,如果你创建一个Fbis对象this指向该对象,也就是说它是否在超类中使用。

答案 4 :(得分:0)

方法F.g()在Fbis中不再存在!

因为你正在“覆盖”Fbis中的方法g()。了解只使用“super.g”将保留覆盖。

答案 5 :(得分:0)

class F {
    void f() {
        System.out.print("F.f() ");
        this.g(); //<----- This line calls Fbis.g() not F.g() 
                  // because this is the instance of Fbis
    }