Java类加载及实例化的调用顺序

1. 没有继承的情况

单独一个类的场景下,初始化顺序为依次为 静态数据,继承的基类的构造函数,成员变量,被调用的构造函数。

其中静态数据只会初始化一次。

package com.khlin.binding.test;

public class App2 {
    public static void main(String[] args) {
        Son son = new Son();
    }
}

class Son {

    public Son() {
        System.out.println("this is son.");
    }

    public Son(int age) {
        System.out.println("son is " + age + " years old.");
    }
    
    private Height height = new Height(1.8f);
    
    public static Gender gender = new Gender(true);
}

class Height {
    public Height(float height) {
        System.out.println("initializing height " + height + " meters.");
    }
}

class Gender {
    public Gender(boolean isMale) {
        if (isMale) {
            System.out.println("this is a male.");
        } else {
            System.out.println("this is a female.");
        }
    }
}

输出:

2. 继承的情况

稍微修改一下代码,添加两个基类,让Son继承Father, Father继承Grandpa。

继承的情况就比较复杂了。由于继承了基类,还将往上回溯,递归地调用基类的无参构造方法。

在我们的例子中,在初始化静态数据后,会先往上追溯,调用Father的默认构造方法,此时再往上追溯到Grandpa的默认构造方法。

注:如果在子类的构造方法中,显式地调用了父类的带参构造方法,那么JVM将调用指定的构造方法而非默认构造方法。

package com.khlin.binding.test;

public class App2 {
    public static void main(String[] args) {
        Son son = new Son();
    }
}

class Grandpa {
    public Grandpa() {
        System.out.println("this is grandpa.");
    }

    public Grandpa(int age) {
        System.out.println("grandpa is " + age + " years old.");
    }

    private Height height = new Height(1.5f);

    public static Gender gender = new Gender(true, "grandpa");
}

class Father extends Grandpa {

    public Father() {
        System.out.println("this is father.");
    }

    public Father(int age) {
        System.out.println("father is " + age + " years old.");
    }

    private Height height = new Height(1.6f);

    public static Gender gender = new Gender(true, "father");
}

class Son extends Father {

    public Son() {
        super(50);
        System.out.println("this is son.");
    }

    public Son(int age) {
        System.out.println("son is " + age + " years old.");
    }

    private Height height = new Height(1.8f);

    public static Gender gender = new Gender(true, "son");
}

class Height {
    public Height(float height) {
        System.out.println("initializing height " + height + " meters.");
    }
}

class Gender {
    public Gender(boolean isMale) {
        if (isMale) {
            System.out.println("this is a male.");
        } else {
            System.out.println("this is a female.");
        }
    }

    public Gender(boolean isMale, String identify) {
        if (isMale) {
            System.out.println(identify + " is a male.");
        } else {
            System.out.println(identify + " is a female.");
        }
    }
}

最后输出会是什么呢?

参考下面另一个案例的分析。链接:http://bbs.csdn.net/topics/310164953 

Java类加载及实例化的调用顺序_第1张图片

在我们的示例中,加载顺序应该是这样的:

Grandpa 静态数据

Father 静态数据

Son 静态数据

Grandpa 成员变量

Grandpa 构造方法

Father 成员变量

Father 构造方法

Son 成员变量

Son 构造方法

所以输出如下:

Java类加载及实例化的调用顺序_第2张图片

你可能感兴趣的:(JAVA)