Java:调用超类'构造函数,该构造函数调用覆盖方法,该方法设置子类的字段

时间:2012-08-23 21:45:16

标签: java override field super

我有这个演示代码:

class Test2 extends Test {
    public int number = 0;

    @Override
    public void set(){
        number = 1;
        info();
    }

    @Override
    public void info(){
        System.out.println(number);
    }
}

public class Test {
    public Test(){
        set();
    }

    public void set(){
    }

    public void info(){
    }

    public static void main(String[] args){
        Test2 object = new Test2();
        object.info();
    }
}

代码给出了这个输出:

1
0

为什么呢?我期待这个输出:

1
1

在我的opionion中,main函数调用Test2类的构造函数来创建一个对象。构造函数自动调用超类'构造函数。此构造函数调用被覆盖的方法set()。因此调用类Test2的方法set()。此方法设置字段并调用写入数字的info()方法。然后main函数再次调用创建对象的info()方法。

正确设置数字字段,因为第一行输出为“1”。但为什么第二行包含0?看来这个领域根本没有设定。你能解释一下吗?

我应该怎样做才能得到我期望的行为?提前谢谢!

3 个答案:

答案 0 :(得分:17)

class Test2 {
    public int number = 0;
}

相当于

class Test2 {
    public int number;

    public Test2() {
        super();
        number = 0;
    }
}

因此,通过调用超级构造函数,字段number设置为1.从超级构造函数返回后,执行number到0的赋值。

只需删除作业,它就应该按照您的预期行事。

答案 1 :(得分:2)

如果说动物延伸狗,你打电话 动物a =新狗()

然后步骤顺序如下

  1. 动物静态字段已初始化

  2. 执行静态动物块

  3. 狗的静态场被初始化<他们将重新初始化 如果动物改变了它们>

  4. 执行静态阻止

  5. 动物的非静态场被初始化它们将是 如果Animal以任何方式更改它们,则重新初始化>

  6. 执行动物构造函数

  7. 初始化的狗的非静态场<如果,他们将重新初始化 动物改变了它们>

  8. 执行狗构造函数

答案 2 :(得分:1)

您的代码在Java中打破了一条黄金法则 - 永远不会在构造函数中调用可被子类覆盖的方法 - 即此类方法应该是私有的。

当Test2中的默认构造函数完成时,它已经覆盖了通过初始化程序public int number = 0;分配给它的初始值1。