一、结论
首先说一下结论
1、一个类
静态变量,静态代码块 → 非静态变量,非静态代码块 → 构造方法
2、有继承关系的父子类中
父类静态变量、父类静态代码块 → 子类静态变量、子类静态代码块 → 父类非静态变量、父类非静态代码块 → 父类构造方法 → 子类非静态变量、子类非静态代码块 → 子类构造方法
二、代码验证
1、一个类中
public class Test2 {
static{
print("静态代码块 1 ");
}
{
print("普通代码块 1 ");
}
public static int i = print("静态变量 i 加载");
public int j = print("普通变量 j 加载 ");
{
print("普通代码块 2");
}
static{
print("静态代码块 2 ");
}
public static int k = print("静态变量 k 加载");
public int l = print("普通变量 l 加载 ");
public Test2() {
print("构造方法");
}
public static void main(String[] args) {
new Test2();
}
public static int print(String string) {
System.out.println(string);
return 0;
}
}
其中静态变量和静态代码块的运行顺序和声明顺序有关,非静态变量和非静态代码块同理。
2、有继承关系的父子类中
public class Test2 {
public static int i = print("父类静态变量 i 加载");
public int j = print("父类非静态变量 j 加载 ");
{
print("父类非静态代码块");
}
static{
print("父类静态代码块");
}
public Test2() {
print("父类构造方法");
}
public static void main(String[] args) {
new Test3();
}
public static int print(String string) {
System.out.println(string);
return 0;
}
}
class Test3 extends Test2{
public static int i = print("子类静态变量 i ");
public int j = print("子类非静态变量 j 加载 ");
static {
print("子类静态代码块");
}
{
print("子类非静态代码块");
}
public Test3() {
print("子类构造方法");
}
}
三、总结
静态变量,静态方法,静态代码块是在类加载的时候就会初始化,并且只初始化一次,那么流程就是:
main方法加载前,两个类都会进行加载,这时候静态变量,静态代码块就会开始加载,如果是有继承关系,会先加载父类再加载子类。然后main方法中new了一个子类的时候,就只会加载实例变量和实例方法,然后调用构造方法同理也是有父类的先调用父类的。
那么现在有了另一个问题,如果在静态变量或者静态代码块中调用了构造方法呢。如下代码
package HomeWork;
public class Test4 {
public Test4() {
print("构造方法");
}
static int count = 0;
static int i = print("静态变量 i 初始化");
static Test4 test4 = new Test4();
int j = print("非静态变量 j 加载");
public static int l = 100;
static {
print("静态代码块");
}
{
print("非静态代码块");
}
public static int print(String str){
System.out.println((count) + ":" + str + "\tl : " + l);
count ++;
l ++;
return 0;
}
public static void main(String[] args) {
new Test4();
}
}
根据运行结果可以看出,当在静态变量中new一个对象的话会加载类中的实例变量和非静态代码块,但不会重新加载一遍非静态变量,并且如果有静态变量未被加载就使用会赋缺省值。