Java有继承时的初始化顺序

public class Beetle extends Insect{
    private int k = print("Test.k initialized.");
    public Beetle() {
        System.out.println("k = " + k);
        System.out.println("j = " + j);
    }
    private static int x2 = print("static Test.x2 initialized.");
    public static void main (String[] args) {
        System.out.println("Beetle constructor.");
        Beetle t = new Beetle();
    }
}

class Insect {
    private int i = 9;
    protected int j;
    Insect() {
        System.out.println("i = " + i + ", j = " + j);
        j = 39;
    }
    Insect(int i) {
        System.out.println("Insect(int i)");
    }
    private  static int x1 = print("static Insect.x1 initialized.");
    static int print(String s) {
        System.out.println(s);
        return 47;
    }
}
得到的输出结果为:
static Insect.x1 initialized.
static Test.x2 initialized.
Beetle constructor.
i = 9, j = 0
Beetle.k initialized.
k = 47
j = 39

继承基类的子类(以下简称子类)的对象创建的初始化过程如下:

1.加载子类的.class文件;

2.通过关键字得知子类有一个基类,继续加载基类的.class文件;若基类还有它的上一层基类则会继续加载;

3.static域的初始化是在类加载完之后就会进行的,最上一层基类加载完,该类的static域便会初始化,此时基类已加载完,static域也已经初始化完毕,再处理第二层基类的static域,对其进行初始化,直到最下层子类的static域初始化完成,此时子类及其所有基类的加载和static域已经初始化完成。

以上三步是在没有创建对象,或者说子类的main方法里没有任何语句时都会执行的,只要运行子类,都会执行类的加载和静态域的初始化。


在beetle上运行Java时,所发生的第一件事情就是试图访问Beetle.main(),于是加数器开始启动井找出Beetle的编译代码
(在名为 Beetle. class的文件之中)。在对它进行加載的过程中,编译器注意到它有一个基类(这是由关键字 extends得知的),
于是它继续进行加载。不管你是否打算产生一个该基类的对象,这都要发生(请尝试将对象创建代码注释掉,以证明这一点)。

如果该基类还有其自身的基类,那么第二个基类就会被加載,如此类推。接下来,根基类
中的 static初始化(在此例中为 Insect)即会被执行,然后是下一个导出类,以此类推,这种方
式很重要,因为导出类的static初始化可能会依赖于基类成员能否被正确初始化
至此为止,必要的类都已加载完毕,对象就可以被创建了。首先,对象中所有的基本类型
都会设为默认值,对象引用被设为null,这是通过将对象内存设为二进制零值而一举生成的
然后,基类的构造器会被调用。在本例中,它是自动调用的。但也可以用super来指定对基类
构造器的调用(正如在Beetle构造器中的第一步操作)。基类构造器和导出类的約造器一样,
以相同的顺序来经历相同的过程。在基类构造器完成之后,实例变量按其次序被初始化。最后
构遺器的其余部分被执行。


故,在创建子类对象的时候,初始化顺序为:
加载文件初始化静态数据–>基类非静态数据初始化–>基类构造器(包括用super指明的,也是先于子类构造器执行)–>子类非静态数据–>子类构造器


public class Beetle extends Insect{
    private int k = print("Beetle.k initialized.");
    public Beetle () {
        super(1);
        System.out.println("k = " + k);
        System.out.println("j = " + j);
    }
    private static int x2 = print("static Beetle.x2 initialized.");
    public static void main (String[] args) {
        System.out.println("Beetle constructor.");
        Beetle t = new Beetle ();
    }
}

class Insect {
    private int i = 9;
    protected int j;
    Insect() {
        System.out.println("i = " + i + ", j = " + j);
        j = 39;
    }
    Insect(int i) {
        System.out.println("Insect(int i)");
    }
    private  static int x1 = print("static Insect.x1 initialized.");
    static int print(String s) {
        System.out.println(s);
        return 47;
    }
}
static Insect.x1 initialized.
static Beetle.x2 initialized.
Beetle constructor.
Insect(int i)
Beetle.k initialized.
k = 47
j = 0

看清楚上面例子中,用super指明构造器时的初始化顺序

你可能感兴趣的:(Java编程思想)