java类初始化中类成员的执行顺序解析
java初始化过程中,代码块,static代码块,实例成员变量,static变量,static方法和普通方法初始化顺序是怎样的呢?
首先看一段代码块,分析其输出打印结果
public class App
{
private static App d = new App();
private SubClass t = new SubClass();
static
{
System.out.println(3);
}
{
System.out.println(5);
}
{
System.out.println(6);
}
public App()
{
System.out.println(4);
}
public static void main(String[] args)
{
System.out.println("hello");
}
}
class SuperClass//父类
{
SuperClass()
{
System.out.println("构造器SuperClass");
}
static
{
System.out.println("superclass静态初始化");
}
}
class SubClass extends SuperClass //子类
{
static
{
System.out.println(1);
}
{
System.out.println(7);
}
public SubClass()
{
//super();
System.out.println(2);
}
}
打印出的答案为:
为什么是这样的结果呢 ??
首先java中共有三种代码块:局部代码块,初始化代码块,静态初始化代码块
1.此题局部代码块不在我们考虑范围
2.初始化代码块(构造代码块):直接定义在类中
每次创建对象的时候都会先执行初始化代码块,通过反编译看到其本质是放到构造器中super()构造器后执行,优先于本类构造器代码先执行,完成初始化.
3.静态初始化代码块:使用static修饰的普通初始化代码块
所在类被加载时按顺序加载到的时候才执行初始化,优先于main方法执行
并且我们先记住3点
1.static修饰的变量和方法是随class的加载而加载并完成初始化的
2.static修饰的变量和方法是按照顺序加载的
3.实例变量是通过new调用构造器创建实例的时候才开始执行初始化的
好接下来我们来分析初始化过程:
1.首先第一步先加载第一个static语句,d声明后储存在方法区中,并调用构造器创建App实例
2.此时构造器会加载非静态变量
①.发现SubClass类型变量,先去包中寻找相关的类,找到SubClass后,再去找其父类SuperClass
②.找到SubClass所有关联类之后,先加载父类字节码文件,此时SuperClass(static代码块完成初始化,打印”superclass静态初始化”),然后再加载SubClass(加载时完成初始化,打印出”1”);
3.加载完关联类之后,调用SubClass构造器,SubClass构造器会默认先调用super()父类构造器输出(“构造器SuperClass”父类构造器总是在子类构造器第一行调用),
然后开始执行子类初始化代码段,其本质是在构造器中初始化,在父类构造器后执行,优先于子类构造器内容执行,输出代码“7”,然后执行子类构造器中代码输出”2”.
4.然后按顺序执行App构造器中初始化代码块,输出“5”“6”,然后执行构造器App()中代码,输出4;
5.实例变量加载完之后,按顺序加载static变量,此时开始加载static代码块,输出3.
6.在加载字节码文件最后执行main方法,输出”hello”
分析完成
最后,按照以上思路,大家分析一下下面代码的打印结果:
public class App
{
private static App d = null;//stataic字段的初始化,
{System.out.println("代码块啊");}
private SubClass t = new SubClass();//非static字段的初始化其实都在构造器中,优先执行的.
static
{
d = new App();
System.out.println(3);
}
public App()
{
//t = new SubClass();
//-----------------------------------
System.out.println(4);
}
public static void main(String[] args)
{
System.out.println("Hello");
}
}
//父类
class SuperClass
{
SuperClass()
{
System.out.println("构造SuperClass");
}
}
//子类
class SubClass extends SuperClass
{
static
{
System.out.println(1);
}
SubClass()
{
//super();//表示调用父类无参数构造器
System.out.println(2);
}
}
运行结果为下图:
大家分析一下能否得到这个结果。