父类构造方法中调用子类动态方法出现的问题

作者在 2008-02-28 14:10:29 发布以下内容

        这篇跟昨天的那篇《构造方法的调用顺序》有联系。我们知道,构造方法的调用顺序以及类的初始化顺序,是先父类的构造方法,然后初始化子类的成员变量,最后才是子类的构造方法。不过里面其中会有些特殊情况让你的程序看起来发生错误。先看下面的一段程序:

public class A extends Father {

public int i = 1;

A() {

//i = 5;

System.out.println("i=" + i);

}

public void p() {

System.out.println("i=" + i);

}

public static void main(String args[]) {

new A();

}

}

class Father {

public int i;

public void p() { }

Father() {

System.out.println("Before p()");

p();

System.out.println("After p()");

}

}

        打印结果是:

Before p()

i=0

After p()

i=1

        首先,Father是A的父类。在Father中,有一个成员变量i,一个方法p(),以及Father的构造方法。A中也有一个成员变量i,并且在定义的时候被初始化为1,同样也有一个打印出i的方法p(),以及A的构造方法。
        程序刚开始运行的时候,从main进入,创建一个A对象。那么,按照昨天讲的,将会先执行Father的构造方法。在Father的构造方法中,先打印出Before p(),然后调用了子类的方法p()。注意,这个时候,我们看到打印出来的是i=0而不是i=1!我们在写子类代码的时候,明明将i初始化为1了,为什么会出现i=0的情况呢?因为,这个时候父类的构造方法还没有执行完毕,子类中的成员变量并没有执行i=1这个初始化过程,而只有系统给出的默认值(int型的是0,boolean型的是false,对象引用是null等等)。所以我们可以看到结果中是i=0而不是i=1。继续往下执行,打印出After p()。这时,父类的构造方法执行完毕。然后就是初始化子类的成员变量,即执行i=1。然后再执行子类A的构造方法,打印出了i=1。
        另外,如果我们去掉类A构造方法的注释,我们会看到如下的结果:

Before p()

i=0

After p()

i=5

        与有注释的结果不同的是最后i=5而不是i=1。这是因为在i被初始化为1之后,我们才执行A的构造方法。而此时构造方法使i=5,然后再打印出i。因此我们看到了i=5。
        所以,我们可以进一步确定类的初始化与构造方法的调用顺序的关系。这里我们要注意的是,尽量不要在父类的构造方法中调用其他的方法,否则会出现一些意想不到的后果。如果的确需要的话,就调用那些是private或者final的方法,因为这些方法不能被子类继承,不是动态调用的方法。

Java | 阅读 3707 次
文章评论,共0条
游客请输入验证码