创建一个Java对象时类构造器执行顺序

当创建任何Java对象时,程序总会先依次调用每个父类的静态代码块,之后在依次调用代码块,父类构造器执行初始化,最后才调用本类的代码块,构造器执行初始化。

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

class Person{
    static String sex = "男";

    {
        String action = "eat";
        System.out.println("Person 类的代码块初始值的action:" + action);
    }

    static{
        System.out.println("Person 类的静态代码块初始值的sex:" + sex);
        String sex = "女";
        System.out.println("Person 类的静态代码块重新赋值后的sex:" + sex);
    }

    String action = "sleep";

    public Person() {
        System.out.println("Person 类的无参构造器");
    }

    public Person(String age) {
        this(); // 显示调用无参构造器
        System.out.println("Person 类的一个参数构造器");
    }

    @Override
    public String toString() {
        return "Person{" +
                "action='" + action + '\'' +
                '}';
    }
}

class Parent extends Person{
    static String sex = "男";

    static{
        System.out.println("Parent 类的静态代码块初始值的sex:" + sex);
        String sex = "女";
        System.out.println("Parent 类的静态代码块重新赋值后的sex:" + sex);
    }

    {
        String action = "eat";
        System.out.println("Parent 类的代码块初始值的action:" + action);
    }

    String action = "sleep";

    public Parent(String age, String name) {
        this(name); // 显示调用Parent一个参数构造器
        System.out.println("Parent带两个参数构造器");
    }

    public Parent(String name) {
        super(name); // 显示调用Parent一个参数构造器
        System.out.println("Parent带一个参数构造器");
    }
}

class Son extends Parent{
    static String sex = "男";

    String action = "sleep";

    {
        System.out.println("Son 类的代码块初始值的action:" + action);
        String action = "eat";
        System.out.println("Son 类的代码块重新赋值后值的action:" + action);
    }

    static{
        System.out.println("Son 类的静态代码块初始值的sex:" + sex);
        String sex = "女";
        System.out.println("Son 类的静态代码块重新赋值后的sex:" + sex);
    }

    public Son() {
        super("java");
        System.out.println("Son 的无参构造器");
    }

    public Son(String name) {
        this();
        System.out.println("Son 带一个参数构造器");
    }
}

执行结果:
Person 类的静态代码块初始值的sex:男
Person 类的静态代码块重新赋值后的sex:女
Parent 类的静态代码块初始值的sex:男
Parent 类的静态代码块重新赋值后的sex:女
Son 类的静态代码块初始值的sex:男
Son 类的静态代码块重新赋值后的sex:女
Person 类的代码块初始值的action:eat
Person 类的无参构造器
Person 类的一个参数构造器
Parent 类的代码块初始值的action:eat
Parent带一个参数构造器
Son 类的代码块初始值的action:sleep
Son 类的代码块重新赋值后值的action:eat
Son 的无参构造器

所以只要在程序创建Java对象,系统总是先依次执行完父类静态代码块,然后调用最顶层父类初始化操作,包括初始化块和构造器,最后依次向下调用所有父类的初始化操作,最终执行本类的初始化操作返回本类的实例。

至于调用父类的哪个构造器执行初始化,则分为以下几种情况

1.子类构造器执行体的第一行代码使用super显示调用父类构造器,系统根据super里的传入的实参数来调用父类哪个构造器

2.子类构造器执行体的第一行代码使用this显示调用本类中重载的构造器,系统根据this里的传入的实参数来调用本类另一个重载构造器

3.子类构造器执行体中既没有super调用,也没有this调用,系统将会在执行子类构造器之前,隐式调用父类无参数的构造器

需要注意的式super调用用于显示调用父类的构造器,this调用用于显示调用本类中另一个重载构造器。super调用和this调用都只能在构造器中使用,而且super调用和this调用都必须作为构造器的第一行代码,因此构造器中的super调用和this调用最多只能使用其中之一,而且最多只能调用一次。

猜你喜欢

转载自blog.csdn.net/note_remark/article/details/80853461