java类的初始化顺序
Java类初始化过程
一、java类的初始化顺序
(1)加载父类(以下序号相同,表明初始化是按代码从上到下的顺序来的)
1.为父类的静态属性分配空间并赋于初值
1.执行父类静态初始化块;
(2)加载子类
2.为子类的静态属性分配空间并赋于初值
2.执行子类的静态的内容;
(3)加载父类构造器
3.初始化父类的非静态属性并赋于初值
3.执行父类的非静态代码块;
4.执行父类的构造方法;
(4)加载子类构造器
5.初始化子类的非静态属性并赋于初值
5.执行子类的非静态代码块;
6.执行子类的构造方法.
总之一句话,静态代码块内容先执行(父先后子),接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法。
二、静态变量和静态代码块的初始化顺序:
谁在前面先初始化谁(这个也比较容易理解,初始化的时候,不可能跳着去初始化吧,比如说静态代码块在静态变量的前面,不可能先跳过静态代码块的初始化先去执行静态变量的初始化吧。)
=====================================================================
对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序是:
(静态变量、静态初始化块)>(变量、初始化块)>构造器。
我们也可以通过下面的测试代码来验证这一点:
public class InitialOrderTest {
public static String staticField = "静态变量"; // 静态变量
public String field = "变量"; // 变量
static { // 静态初始化块
System.out.println(staticField);
System.out.println("静态初始化块");
}
{ // 初始化块
System.out.println(field);
System.out.println("初始化块");
}
public InitialOrderTest() { // 构造器
System.out.println("构造器");
}
public static void main(String[] args) {
new InitialOrderTest();
}
}
运行以上代码,我们会得到如下的输出结果:
静态变量
静态初始化块
变量
初始化块
构造器
这与上文中说的完全符合。那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果:
class Parent {
public static String p_StaticField = "父类--静态变量"; // 静态变量
public String p_Field = "父类--变量"; // 变量
static { // 静态初始化块
System.out.println(p_StaticField);
System.out.println("父类--静态初始化块");
}
{ // 初始化块
System.out.println(p_Field);
System.out.println("父类--初始化块");
}
public Parent() { // 构造器
System.out.println("父类--构造器");
}
}
public class SubClass extends Parent {
public static String s_StaticField = "子类--静态变量"; // 静态变量
public String s_Field = "子类--变量"; // 变量
static { // 静态初始化块
System.out.println(s_StaticField);
System.out.println("子类--静态初始化块");
}
{ // 初始化块
System.out.println(s_Field);
System.out.println("子类--初始化块");
}
public SubClass() { // 构造器
System.out.println("子类--构造器");
}
// 程序入口
public static void main(String[] args) {
new SubClass();
}
}
运行一下上面的代码,结果马上呈现在我们的眼前:
父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
父类--变量
父类--初始化块
父类--构造器
子类--变量
子类--初始化块
子类--构造器
现在,结果已经不言自明了。大家可能会注意到一点,那就是,并不是父类完全初始化完毕后才进行子类的初始化,实际上子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。
那么对于静态变量和静态初始化块之间、变量和初始化块之间的先后顺序又是怎样呢?是否静态变量总是先于静态初始化块,变量总是先于初始化块就被初始化了呢?实际上这取决于它们在类中出现的先后顺序。我们以静态变量和静态初始化块为例来进行说明。
同样,我们还是写一个类来进行测试:
public class TestOrder {
public static TestA a = new TestA(); // 静态变量
static { // 静态初始化块
System.out.println("静态初始化块");
}
public static TestB b = new TestB(); // 静态变量
public static void main(String[] args) {
new TestOrder();
}
}
class TestA {
public TestA() {
System.out.println("Test--A");
}
}
class TestB {
public TestB() {
System.out.println("Test--B");
}
}
运行上面的代码,会得到如下的结果:
Test--A
静态初始化块
Test--B
大家可以随意改变变量a、变量b以及静态初始化块的前后位置,就会发现输出结果随着它们在类中出现的前后顺序而改变,这就说明静态变量和静态初始化块是依照他们在类中的定义顺序进行初始化的。同样,变量和初始化块也遵循这个规律。