父类和子类构造顺序和时机-转载

上一篇 / 下一篇  2011-07-04 15:19:08 / 个人分类:JAVA

/**
 * @(#)TestJava.java 2008-2-22
 * 
 * Copyright 2007 GeneralData, Inc. All rights reserved.
 
*/
package com.bbebfe;

/**
 * 这个类测试父类和子类的构造时机
 * 父类中有一个(抽象)方法prt();
 * 子类(实现)覆盖了这个方法,并打印"in child" + i,i是
 * 子类中定义的一个成员字段,设定初值为10。
 * 
 * 在父类的构造中调用prt(),
 * 如果能够调用成功,说明子类对象在子类的构造方法执行前
 * 已经在内存中构造好了(因为父类的构造方法会在子类的构造
 * 方法前执行),因为如果子类对象没有在内存中存在,则
 * 不可能执行打印,更不能打印成员字段i。
 * 
 * 最终的执行结果是成功打印"in child 0",说明能够执行打印,
 * 说明子类对象的内存已经分配。
 * 但i的值打印为0,说明内存虽然已经分配,但成员字段尚未执行显示初始化,
 * 默认初始化为0。
 * 在Child的构造中打印i的值为10,说明成员字段的显示初始化在内存分配
 * 和构造体之间进行。
 * 
 * 因此可以看出一个Java对象的具体构造过程(不包含静态结构):
 * 1. 父类对象内存分配
 * 2. 父类字段默认初始化
 * 3. 子类对象内存分配
 * 4. 子类字段默认初始化
 * 5. 进入父类构造-> 父类成员显示初始化(定义字段时设置的字段初值)
 *         -> 执行父类构造体(此时可以调用抽象方法,所有父类字段已初始
 *             化完毕,但子类字段尚未进行显示初始化)
 * 6. 进入子类构造-> 子类成员显示初始化(定义字段时设置的字段初值)
 *         -> 执行子类构造体(此时所有字段已经显示初始化) 
 * 
 * 因此,父类的构造中可以调用抽象方法(子类实现),但最好
 * 不要这样做,因为子类对象仅仅分配了内存和默认初始化,还没有
 * 进行显示初始化。
 * @project TestJava
 * 
@author chenhao
 * 
@version 1.0.0, 2008-2-22
 
*/
public class TestJava {

    
public static void main(String[] args) {
        Child c 
= new Child();
    }
}
class Child extends Father
{
    
int i = 10;
    
/**
     * 这个构造方法是没有必要写的,因为默认构造
     * 肯定是按这个顺序执行的。但为了表示明确的
     * 目的,因此把这个默认构造写出来
     *
     
*/
    
public Child() {
        
super();
        System.out.println(i);
    }
    @Override
    
public void prt() {
        System.out.println(
"in child i = " + i + " k = " + k);
    }
}

abstract class Father
{
    
protected int k = 5;
    
public Father() {
        prt();
    }
    
public void prt() {
        System.out.println(
"in Father k = " + k);
    }
}

TAG:

seven_zhao的个人空间 引用 删除 seven_zhao   /   2011-12-16 14:53:25
@散步的Sun
呵呵,我只是初步阶段。经常去你的空间,学习了不少东西,谢谢你的分享。
散步的SUN的个人空间 引用 删除 散步的SUN   /   2011-12-14 18:52:04
呵呵,看样子你也喜欢java
 

评分:0

我来说两句

Open Toolbar