import static mylib.Print.*;
public class InitTest{
public static void main(String[] args){
new Three();
}
}
class One {
private static String a = getString("One static data init");
private static String b;
static {
print("one static block");
print(b);
}
private static String c = getString("one static data init 2");
private String d = getString("One data init 1");
public static String getString(String s){
print(s);
return s;
}
One(){
print("One constructor");
this.overrrideMethod();
}
public void overrrideMethod(){
print("one overri");
this.b = "one has been init";
}
}
class Two extends One {
private static String a = getString("Two static data init");
private static String b;
static {
print("Two static block");
print(b);
}
private static String c = getString("Two static data init 2");
private String d = getString("Two data init 1");
Two(){
print("Two constructor");
this.overrrideMethod();
}
@Override
public void overrrideMethod(){
print("two overri");
this.b = "two has been init";
}
}
class Three extends Two {
private static String a = getString("Three static data init");
private static String b;
static {
print("Three static block");
print(b);
}
private static String c = getString("Three static data init 2");
private String d = getString("Three data init 1");
Three(){
print("Three constructor");
this.overrrideMethod();
}
@Override
public void overrrideMethod(){
print("three overri");
this.b = "three has been init";
}
}
运行结果
One static data init
one static block
null
one static data init 2
Two static data init
Two static block
null
Two static data init 2
Three static data init
Three static block
null
Three static data init 2
One data init 1
One constructor
three overri
Two data init 1
Two constructor
three overri
Three data init 1
Three constructor
three overri
由以上代码的运行结果可以看出,java在创建一个对象时的初始化顺利如下:
- 基类1的静态成员初始化,基类2的静态成员初始化…最后一个子类的静态成员初始化(静态块和普通的静态成员在初始化顺序上没有什么区别,按照书写顺序决定初始化顺序)
- 对对象中的方法进行后期绑定(由在静态块中输出的b是null,确定后期绑定发生在静态成员初始化之后,由每个构造函数中输出的都是three overri确定后期绑定是发生在构造函数调用之前。)
- 基类1的数据成员初始化,调用基类1的构造函数。基类2的数据成员初始化调用基类2的构造函数。
- 初始化完成
总结下来就是,先静态初始化,然后后期绑定,继而数据成员初始化,最后调用构造函数
值得注意的是,不论继承的链条多长,所有的静态初始化都发生在数据成员初始化和构造函数调用之前。而数据成员初始化和构造函数调用则是按照继承的链条依次进行的。