Java的执行代码具有相应的顺序:
类加载阶段:
- 当JVM第一次主动使用某个类时,系统会在 类准备阶段 为该类的所有静态Field分配内存,
- 所以初次出现的静态Field必须声明数据类型,静态初始化代码里面再次出现时不能声明数据类型,否则会被系统识别为两个Field。
- 在 初始化阶段 则负责 初始化这些静态Field,初始化静态Field就是执行 静态初始化代码 或者 声明静态Field时指定的初始值,
- 它们的执行顺序与源代码中的排列顺序相同。
对象创建阶段:
-
当Java创建一个对象时,系统先为该对象的所有实例Field分配内存(前提是该类已经被加载过了),
-
所以初次出现的实例Field必须声明数据类型,初始化代码里面再次出现时不能声明数据类型,否则会被系统识别为两个Field。
-
接着程序开始对这些实例Field执行初始化,其初始化顺序是:先执行初始化块或声明Field时指定的初始值,
-
它们的执行顺序与源代码中的排列顺序相同,再执行构造器里指定的初始值。
-
父类静态Field --> 父类静态代码块 --> 子类静态Field --> 子类静态代码块 --> 父类非静态Field --> 父类非静态代码块 --> 父类构造方法 --> 子类非静态Field --> 子类非静态代码块 --> 子类构造方法
public class Test5 {
public static void main(String[] args) {
Son son = new Son();
System.out.println(son.n);
System.out.println(Son.m);
}
}
class Son extends Father {
int n = 300;
String string = "子类实例变量";
static int m = 1000;
static String stringStatic = "子类类变量";
{
n = 200;
System.out.println("子类非静态代码块");
System.out.println("===========");
}
static {
m = 2000;
System.out.println("子类静态代码块");
System.out.println("===========");
}
public Son() {
System.out.println("子类构造方法");
System.out.println("===========");
}
}
class Father {
String string = "父类实例变量";
static String stringStatic = "父类类变量";
{
System.out.println("父类非静态代码块");
System.out.println("===========");
}
static {
System.out.println("父类静态代码块");
System.out.println("===========");
}
public Father() {
System.out.println("父类构造方法");
System.out.println("===============");
}
}