最近在刷牛客网的题目看到有关静态代码块、构造代码块、构造方法的执行顺序的问题,因为基础不牢固没选出正确答案,当然要将这个知识点重新掌握,写篇博客来记录一下学习的过程。
先了解一下相关概念:
- 静态代码块:在类中以static关键字声明的代码块,随类的加载而执行
//父类静态代码块一
static {
System.out.println("父类静态代码块一,只会执行一次");
}
- 构造代码块:在类中以{}括起来的代码块,随对象的创建而执行
//父类构造代码块
{
System.out.println("父类构造代码块");
}
- 普通代码块:出现在方法中以{}括起来的代码块
{
System.out.println("主方法中的普通代码块一");
}
- 构造方法:这个不解释了
测试代码:
package com.youngpain;
class Parent {
//父类静态代码块一
static {
System.out.println("父类静态代码块一,只会执行一次");
}
//父类静态成员变量
private static int age = getAge();
//父类普通成员变量
private String car = getCar();
//父类构造方法
public Parent() {
System.out.println("父类构造方法");
}
//父类构造代码块一
{
System.out.println("父类构造代码块一");
}
public String getCar() {
System.out.println("父类普通成员变量初始化");
return "Benz";
}
//父类构造代码块二
{
System.out.println("父类构造代码块二");
}
public static int getAge() {
System.out.println("父类静态成员变量初始化");
return 30;
}
//父类静态代码块二
static {
System.out.println("父类静态代码块二,只会执行一次");
}
}
class Son extends Parent {
//子类静态成员变量
private static String name = getName();
//子类构造方法
public Son() {
System.out.println("子类构造方法");
}
//子类构造代码块
{
System.out.println("子类构造代码块");
}
//子类静态代码块
static {
System.out.println("子类静态代码块,只会执行一次");
}
//子类普通成员变量
private double height = getHeight();
public static String getName() {
System.out.println("子类静态成员变量初始化");
return "Son";
}
public double getHeight() {
System.out.println("子类普通成员变量初始化");
return 1.65;
}
}
public class LoadOrderTest {
public static void main(String[] args) {
{
System.out.println("主方法中的普通代码块一");
}
System.out.println("创建第一个子类对象----------------------------");
Son son1 = new Son();
System.out.println("创建第二个子类对象----------------------------");
Son son2 = new Son();
{
System.out.println("主方法中的普通代码块二");
}
}
}
执行结果:
主方法中的普通代码块一
创建第一个子类对象----------------------------
父类静态代码块一,只会执行一次
父类静态成员变量初始化
父类静态代码块二,只会执行一次
子类静态成员变量初始化
子类静态代码块,只会执行一次
父类普通成员变量初始化
父类构造代码块一
父类构造代码块二
父类构造方法
子类构造代码块
子类普通成员变量初始化
子类构造方法
创建第二个子类对象----------------------------
父类普通成员变量初始化
父类构造代码块一
父类构造代码块二
父类构造方法
子类构造代码块
子类普通成员变量初始化
子类构造方法
主方法中的普通代码块二
结果分析:
- 先执行父类静态代码块和初始化父类的静态成员变量,如果有多个静态代码块,执行顺序取决于静态代码块的位置
- 再执行子类静态代码块和初始化子类的静态成员变量,这里父类和子类中静态代码块和静态成员变量的位置相反,因此执行的顺序相反
- 然后初始化父类普通成员变量,再执行父类构造代码块,如果有多个构造代码块,执行顺序取决于构造代码块的位置
- 接着执行父类构造方法
- 如果同时存在子类构造代码块和子类普通成员变量,谁在前就先执行或初始化
- 最后执行子类的构造方法
- 静态代码块和静态成员变量只会执行一次或初始化一次,构造代码块和普通成员变量每次创建对象都会执行或初始化
总结:
父类静态代码块(静态成员变量)>子类静态代码块(静态成员变量)>父类构造代码块(普通成员变量)>父类构造方法>子类构造代码块(普通成员变量)>子类构造方法
PS:个人总结,如有错误,敬请指正,不胜感谢!