class B{
public B(){
System.out.println("B构造方法");
}
public static int x_b = printInt("B static init");
public int y_b = printInt("B no static init");
public static int printInt(String s){
System.out.println(s);
return 0;
}
}
class C extends B{
public C(){
System.out.println("C构造方法");
}
public static int x_c = printInt("C static init");
public int y_c = printInt("C no static init");
}
class D extends C{
public D(){
System.out.println("D构造方法");
}
public static int x_d = printInt("D static init");
public int y_d = printInt("D no static init");
}
public class Main {
public static void main(String[] args) throws InterruptedException {
System.out.println(D.x_d);
new D();
}
}
运行结果:
在main中,打印D中的静态变量x_d,会初始化D中的所有静态变量。根据结果输出,静态变量的初始化顺序是先初始化基类中的静态变量。当new一个新的D对象(子类)时,会先初始化基类中的变量,然后是基类中的构造方法,接着才会初始换子类中的变量,然后构造方法。因为在这里,打印语句已经触发静态变量的唯一一次初始换,所以new对象的时候就不会再初始化static变量了。
总结:
当new一个子类的对象,顺序如下:
基类static变量>子类static变量>基类非static变量>基类构造方法>子类非static变量>子类构造方法
具体可以参考JVM中的类加载机制,在加载子类的时候,要先保证基类已经加载进来了