类和对象的混合初始化以及静态成员之前的初始化顺序

前言

java version "1.8.0_172"
Java(TM) SE Runtime Environment (build 1.8.0_172-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.172-b11, mixed mode)

概念

静态成员:
包括静态变量,静态成员方法以及静态代码块。
类的初始化:
类成员变量(静态成员变量)进行赋值的过程。
对象的初始化
普通成员变量进行赋值的过程。

结论

静态成员之间没有执行优先级,只会按照顺序执行。

代码分析

public class Father {
    static String str1 = "父类属性str1";
    static String str2 = getStr2();

    static {
        System.out.println(str2);//这里能够使用str2变量,说明代码块和变量之间没有优先级
        System.out.println("父类代码块1");
//        System.out.println(str3);//这里使用str3报错说明,代码块和变量之间是按照先后顺序执行的
    }
//    static String str3 = "父类属性str3";
    public static String getStr2() {
        System.out.println("父类方法getStr2");

        return "父类属性str2";
    }
    static {
        System.out.println("父类代码块2");
    }
    public static void getStr3() {
        System.out.println("父类方法getStr3");
    }
}

类和对象混合初始化

分析总结放到了最后。

分析过程代码

public class Son extends Father{
    String comStr1 = getSonComStr1();
    String comStr2 = "子类静态变量2";
    static String staStr1 = getStaStr1();
    static String staStr2 = "子类静态变量2";

    private String getSonComStr1() {
        System.out.println("子类普通方法1");
        return "子类普通变量1";
    }
    private static String getStaStr1() {
        System.out.println("子类静态方法1");
        return "子类静态变量1";
    }
    {
        System.out.println("子类普通代码块1");
    }
    static {
        System.out.println("子类静态代码块1");
    }
    public Son() {
        //super();//每一个构造方法的首行都有一个隐藏的super()语句,调用父类无参构造
        System.out.println("子类无参构造函数");
    }
    {
        System.out.println("子类普通代码块2");
    }
    static {
        System.out.println("子类静态代码块2");
    }
}

class Father {
    String comStr1 = getFatherComStr1();
    String comStr2 = "父类静态变量2";
    static String staStr1 = getStaStr1();
    static String staStr2 = "父类静态变量2";

    private String getFatherComStr1() {
        System.out.println("父类普通方法1");
        return "父类普通变量1";
    }
    private static String getStaStr1() {
        System.out.println("父类静态方法1");
        return "父类静态变量1";
    }
    {
        System.out.println("父类普通代码块1");
    }
    static {
        System.out.println("父类静态代码块1");
    }
    public Father() {
        //super();//每一个构造方法的首行都有一个隐藏的super()语句
        System.out.println("父类无参构造函数");
    }
    {
        System.out.println("父类普通代码块2");
    }
    static {
        System.out.println("父类静态代码块2");
    }
}

结果展示

父类静态方法1
父类静态代码块1
父类静态代码块2
子类静态方法1
子类静态代码块1
子类静态代码块2
父类普通方法1
父类普通代码块1
父类普通代码块2
父类无参构造函数
子类普通方法1
子类普通代码块1
子类普通代码块2
子类无参构造函数

分析过程

  1. new Son();
  2. 扫描子类和父类中的静态成员,并进行优先初始化。这里输出
父类静态方法1
父类静态代码块1
父类静态代码块2
子类静态方法1
子类静态代码块1
子类静态代码块2

这里其他静态成员也初始化了,但是并没有输出。并且从这里可以看出,先初始化父类静态成员,后初始化子类静态成员。
3. 进入子类无参构造方法,在首行遇到super()

public Son(){
    super();//执行到这,然后进入该方法。
}
  1. 进入super()方法。
public Father() {
    //super();//每一个构造方法的首行都有一个隐藏的super()语句
    System.out.println("父类无参构造函数");
}

注意,这里Father类的无参构造首行仍然有一个super(),执行Object类的无参构造。
5. 父类无参构造中的super()执行结束,回到父类,从头开始初始化,一直到最后。届时,父类中所有成员均被初始化。(这一步仅初始化的是非静态成员,因为在在步骤2中父类中的所有静态成员已被提前初始化。)

class Father {
    String comStr1;//即来到这个地方。
    ...
}//然后一直到结束,父类中的所有成员均被初始化。

该步骤执行输出:

父类普通方法1
父类普通代码块1
父类普通代码块2
  1. 父类所有成员初始化结束,回到父类无参构造super()处,继续向下父类无参构造方法中的语句。
public Father(){
    //super();
    System.out.println("父类无参构造函数");//执行这步。
}

输出:

父类无参构造函数
  1. 这时父类中所有代码执行完毕,回到子类,从子类类的首行开始向下执行,末尾结束。这步同步骤5
public class Son extends Father{
    String comStr1 = getSonComStr1();//由此开始执行。
    ...
}

输出:

子类普通方法1
子类普通代码块1
子类普通代码块
  1. 子类所有成员初始化完毕,回到子类无参super()处,继续向下执行无参构造中的代码。
public Son() {
    //super();//每一个构造方法的首行都有一个隐藏的super()语句,调用父类无参构造
    System.out.println("子类无参构造函数");//从此往下执行
}

输出:

子类无参构造函数
  1. 致此,结束,返回main方法。

总结

执行顺序:
静态成员(父类>子类) > 父类成员和方法(构造方法>父类其他)> 子类成员和方法(构造方法>子类其他)

1. 针对一个类:静态>构造>普通。
2. 有静态先执行静态,不管是子类静态还是父类静态。
3. 同级别间没有优先级,按照顺序执行。
4. 父类>子类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值