Java中类的加载顺序
2018-08-23 本文已影响0人
BigDreamMaker
以前对类的加载顺序,静态变量的初始化,普通变量的初始化,构造函数的初始化,构造代码块,静态代码块的初始化顺序一直搞不清楚,于是乎今天特别的做了一下,记录。
为了完成今天的测试,先给出测试类。
1.测试类
- 父类
public class Father {
static String staticVar1 = LoaderUtils.getMemberValue("[父类]静态变量1");
static String staticVar2 = LoaderUtils.getMemberValue("[父类]静态变量2");
String normalVar1 = LoaderUtils.getMemberValue("[父类]普通变量1");
String normalVar2 = LoaderUtils.getMemberValue("[父类]普通变量2");
{
System.out.println("[父类]匿名构造函数初始化");
}
static {
System.out.println("[父类]静态匿名构造函数初始化");
}
Father() {
System.out.println("[父类]无参构造函数初始化");
}
}
- 子类
public class Son extends Father {
static String staticVar1 = LoaderUtils.getMemberValue("[子类]静态变量1");
static String staticVar2 = LoaderUtils.getMemberValue("[子类]静态变量2");
String normalVar1 = LoaderUtils.getMemberValue("[子类]普通变量1");
String normalVar2 = LoaderUtils.getMemberValue("[子类]普通变量2");
{
System.out.println("[子类]匿名构造函数初始化");
}
static {
System.out.println("[子类]静态匿名构造函数初始化");
}
public Son() {
System.out.println("[子类]无参构造函数初始化");
}
}
- LoaderUtils:用于对静态,非静态成员变量进行赋值和控制台输出。
public class LoaderUtils {
public static String getMemberValue(String input) {
System.out.println(input);
return input;
}
}
- 客户端
public static void main(String[] args) {
System.out.println("***************第[1]次调用构造函数**************");
Son son1 = new Son();
System.out.println("***************第[2]次调用构造函数**************");
Son son2= new Son();
System.out.println("***************第[3]次调用构造函数**************");
Son son3 = new Son();
}
- 输出结果
***************第[1]次调用构造函数**************
[父类]静态变量1
[父类]静态变量2
[父类]静态匿名构造函数初始化
[子类]静态变量1
[子类]静态变量2
[子类]静态匿名构造函数初始化
[父类]普通变量1
[父类]普通变量2
[父类]匿名构造函数初始化
[父类]无参构造函数初始化
[子类]普通变量1
[子类]普通变量2
[子类]匿名构造函数初始化
[子类]无参构造函数初始化
***************第[2]次调用构造函数**************
[父类]普通变量1
[父类]普通变量2
[父类]匿名构造函数初始化
[父类]无参构造函数初始化
[子类]普通变量1
[子类]普通变量2
[子类]匿名构造函数初始化
[子类]无参构造函数初始化
***************第[3]次调用构造函数**************
[父类]普通变量1
[父类]普通变量2
[父类]匿名构造函数初始化
[父类]无参构造函数初始化
[子类]普通变量1
[子类]普通变量2
[子类]匿名构造函数初始化
[子类]无参构造函数初始化
2.结果分析
在本例中Son继承Father,并且在子,父类中分别定义了,静态变量,静态代码块,普通变量,构造代码块和构造函数。
由结果可以看出,在第一次调用构造函数的过程中,虽然子类Son没有显示的调用父类的无参构造,但是Java会帮我们完成调用父类无参构造的过程。
- 静态代码只会执行一次。
从上面3次的输出结果可以看出,静态代码的初始化只有第一次new对象的时候会执行,之后再new对象则不再执行静态代码的初始化。 - 静态优于非静态
并且静态代码要优先于非静态代码先执行初始化。 - 父类初始化先于子类初始化。
在本例中,无论是静态还是非晶态资源的初始化,父类的初始化动作总是先于子类的初始化。 - 初始化顺序和声明顺序相同
无论是静态代码块,静态变量 。还是普通变量,构造代码块。他们的执行顺序和他们再类中的声明顺序有关,在前面的先执行,在后面的后执行。 - 构造函数总是在最后执行。
总结下来就是
- 先静态后普通。
- 先父类后子类。
- 静态,非静态资源的初始化顺序等于其声明顺序。
- 构造函数总在最后执行。