Java继承基类使用派生类方法

时间:2013-11-02 20:31:18

标签: java inheritance

最近我偶然发现了Java测试并发现了一种奇怪的行为。

class MainOne {

    private int i = 5;

    public MainOne() {
        System.out.println("MainOne says that I is " + getI());
    }

    public int getI() {
        System.out.println("MainOne getI was used");
        return i;
    }

}

public class TheTest extends MainOne {

    private static int i = 10;

    public TheTest() {
        System.out.println("TheTest says that I is " + super.getI());
    }


    public int getI() {
        System.out.println("TheTest getI was used");
        return i;
    }

    public static void main(String[] args) {
        TheTest test = new TheTest();
    }

}

结果是:

  

使用了测试getI

     

MainOne说我才10岁。

     

使用MainOne getI

     

TheTest说我是5岁

问题是,发生了什么?为什么Base类使用它后代的方法?

2 个答案:

答案 0 :(得分:5)

这完全是关于执行顺序和构造函数继承。 TheTest构造函数隐式调用super MainOne构造函数。

所以

public TheTest() {
    System.out.println("TheTest says that I is " + super.getI());
}

来电

public MainOne() {
    System.out.println("MainOne says that I is " + getI());
}

由于多态性而调用覆盖getI()

public int getI() {
    System.out.println("TheTest getI was used");
    return i;
}

此处的istatic i中声明的TheTest。最后

super.getI());

被调用,使用MainOne的{​​{1}}。

你得到

i

请注意,多态不适用于字段,并且该字段(无论TheTest getI was used MainOne says that I is 10. MainOne getI was used TheTest says that I is 5 还是实例)可能会隐藏父类中相同名称的字段。

答案 1 :(得分:0)

这个问题有两点需要注意。

  1. MainOne

    中的super.getI()调用
    public TheTest() {
        System.out.println("TheTest says that I is " + super.getI());
    }
    

    强行将此调用转到超类,即使该方法被覆盖。

  2. 子类中的字段i被定义为static字段

    根据该字段是否为静态,结果存在差异。当从getI()构造函数调用重写的TheTest时,调用将转到MainOne类方法。但是,当发生此调用时,TheTest类的实例字段尚未初始化为指定的值(但仅为默认值)。

    如果i中的字段TheTest是实例字段,则getI()将打印0而不是10。

    这里很难说明调用顺序的细节。但是,如果您想了解更多详细信息,请参阅以下内容。

    new TheTest()
        -> super() - implicitly invoke default constructor
            -> inside MainOne() constructor
                -> System.out.println("MainOne says that I is " + getI());
                    -> this results in a getI() invocation
                    -> since getI() is overridden by subclass
                    -> invoke on TheTest instance, not MainOne class.
                    -> TheTest's instance fields not given the assigned values
                    -> TheTest's static fields have got the assigned values
                <- string concatenation completes for System.out.println()
            <- MainOne constructor (or the super) is completed
        <- super() completes
    
        -> System.out.println("TheTest says that I is " + super.getI());
            -> this results in a getI() invocation
            -> however explicit super.getI() forcefully goes to super class
            -> invoke on MainOne (super) instance, not TheTest class.
        <- string concatenation completes for System.out.println()
    <- new TheTest() constructor completes
    
  3. 希望这有助于您进一步了解细节。