Java的静态变量,成员变量,静态代码块,构造块的加载顺序

时间:2022-03-19 19:32:42

在开始本博客写作之前请大家看一道经典的java面试题

public class StaticTest{

    public static void main(String args[]){
staticFunction();
}
static StaticTest st = new StaticTest();
static{
System.out.println("1");
}
StaticTest(){
System.out.println("3");
System.out.println("a="+a+" b="+b);
}
public static void staticFunction(){
System.out.println("4");
}
{
System.out.println("2");
}
int a=100;
static int b=112;
}
最后的答案是:
2
3
a=100 b=0
1

对于这个执行结果是不是有些让你大跌眼镜呢?那么现在本菜鸟就来分析分析:对于静态成员变量和静态代码块而言,初始化的顺序是按照出现顺序;当有父类静态代码块或者父类静态成员变量的时候,不管出现顺序如何,先初始化父类的,

面试题详解,从类的生命周期和对象的初始化来分析:

1.类的生命周期是:加载->验证->准备->解析->初始化->使用->卸载,只有在准备阶段和初始化阶段才会涉及类变量的初始化和赋值,因此只针对这两个阶段进行分析;
2.类的准备阶段需要做是为类变量分配内存并设置默认值,因此类变量st为null、b为0;(需要注意的是如果类变量是final在加载阶段就已经完成了初始化,可以把b设置为final试试);
3.类的初始化阶段需要做是执行类构造器(类构造器是编译器收集所有静态语句块和类变量的赋值语句按语句在源码中的顺序合并生成类构造器,对象的构造方法是init,类的构造方法是cinit,可以在堆栈信息中看到),因此先执行第一条静态变量的赋值语句即st = new StaticTest (),此时会进行对象的初始化,对象的初始化是先初始化成员变量再执行构造方法,因此打印2->设置a为110->执行构造方法(打印3,此时a已经赋值为110,但是b只是设置了默认值0,并未完成赋值动作),等对象的初始化完成后继续执行之前的类构造器的语句,接下来就详细说下:

首先执行语句: static StaticTest st = new StaticTest();这个语句等价于static{StaticTest st = new StaticTest() },StaticTest st = new StaticTest(),这个会先执行StaticTest类的成员变量和构造代码块,所以会先执行{System.out.println("2");}这个构造代码块,得出结果2,然后执行 int a=100;这个语句。然后执行StaticTest (){}构造方法,打印出3,a=100 b=0,最后执行static{    System.out.println("1");这个静态代码块,结果为1