我面临一个混乱。

这是我的小代码段

public class Father {

    public String x;

    public Father() {
        this.init();
        System.out.println(this);
        System.out.println(this.x);
    }

    protected void init() {
        x = "Father";
    }

    @Override
    public String toString() {
        return "I'm Father";
    }

    void ParentclassMethod(){

        System.out.println("Parent Class");
    }

}


public class Son extends Father {
    public String x;


    @Override
    protected void init() {
        System.out.println("Init Called");

        x = "Son";
    }

    @Override
    public String toString() {
        return "I'm Son";
    }

    @Override
    void ParentclassMethod(){
        super.ParentclassMethod();
        System.out.println("Child Class");
    }

}

public class MainCLass{

    public static void main(String[] args){

        Son ob = new Son();

}


因此,当我创建继承自Class Father的Son的类实例时,JVM会自动调用父亲的类构造函数。当父亲的构造函数调用否则会初始化父亲的字段时,它将创建Son类型的实例。到目前为止好..!

如您所见,字段x从父亲的班级派生到儿子的班级。
我的代码使用x方法初始化init()

那么为什么它显示为空。

它非常混乱。有人可以解释吗?

最佳答案

变量在Java中不是多态的。由于您在x中重新声明了Son,因此该变量实际上是与x中的变量不同的Father。因此,在initSon方法中,您正在初始化Sonx,而不是Fatherx

另一方面,您的语句System.out.println(this.x);Father类内部,因此它仅了解Fatherx。由于不再通过覆盖init方法来初始化此变量,因此x中的Father保留为null(默认值),因此将打印null

您可以通过从public String x;类中删除Son来解决此问题。这将使Fatherx成为唯一的x,从而消除了问题。

但是,通常,您希望将此变量设置为private而不是public。您也不应在构造函数中调用非final方法。 It can only introduce bugs。在这种情况下,初始化它的正确方法是在Father中使用带有参数的构造函数:

public class Father {
    private String x;

    protected Father(String x) {
        this.x = x;
        System.out.println(this);
        System.out.println(this.x);
    }

    public Father() {
        this("Father");
    }

    // Rest of father's code, without the init method
}

public class Son extends Father {
    public Son() {
        super("Son");
    }

    // Rest of son's code, without the init method
}

关于java - 父项和子项字段如何在继承中初始化?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54743800/

10-13 03:09