Java父类子类加载顺序
父类如下:
package zzm.java.extendsDemo; public class Parent { /** * 会报错,因为static按顺序进行加载的 */ // static { // System.out.println("i="+i); // } public static int i = 0; { i++; System.out.println("i(非静态)="+i); } static { i = i+1; System.out.println("i(静态)="+i); } { i++; System.out.println("i(非静态)="+i); } public Parent(){ i++; System.out.println("i(构造方法)="+i); } }
子类如下:
package zzm.java.extendsDemo; public class Child extends Parent{ public static int i = 0; { i++; System.out.println("i(子类非静态)="+i); } static { i = i+1; System.out.println("i(子类静态)="+i); } { i++; System.out.println("i(子类非静态)="+i); } public Child(){ //显示调用父类构造方法,必须放在最前面,和不写是一样的 super(); i++; System.out.println("i(子类构造方法)="+i); } public static void main(String[] args) { Child child1 = new Child(); Child child2 = new Child(); } }
猜猜输出是啥?
下面是打印
i(静态)=1 i(子类静态)=1 i(非静态)=2 i(非静态)=3 i(构造方法)=4 i(子类非静态)=2 i(子类非静态)=3 i(子类构造方法)=4 i(非静态)=5 i(非静态)=6 i(构造方法)=7 i(子类非静态)=5 i(子类非静态)=6 i(子类构造方法)=7
由此我们得出下面几个结论:
1、先执行父类的静态变量、静态方法块,谁在前面谁先执行
2、在执行子类的静态变量、静态方法块,也是一样,谁在前面谁先执行
3、在执行父类的非静态变量、非静态方法块,接着执行对应子类
4、最后在执行父类构造方法、在执行子类构造方法
5、当类已经被加载后,第二次加载时不会在执行静态变量的赋值,已经静态方法块,但是会执行非静态变量的赋值和非静态方法块。
因为一个静态变量的初始化是在类加载的准备阶段,这个阶段会执行静态变量的赋值以及相关的静态代码块,是<client>()方法执行的,执行时机是类加载的时候
而非静态方法,是由<init>()方法执行的,执行时间是构造实例的时候,随着实例化时一起放在堆上