Java 继承关系中:static,构造函数,成员变量的加载顺序
首先看下面的例子:
package simple.demo; /** * @author Administrator * @date 2019/01/03 */ public class ClassA { ClassB classB1 = new ClassB(); static { System.out.println("ClassA static========="); ClassB classB2 = new ClassB(); } public ClassA(){ System.out.println("ClassA 构造函数========="); } }
package simple.demo; /** * @author Administrator * @date 2019/01/03 */ public class ClassB { static { System.out.println("ClassB static========="); } public ClassB(){ System.out.println("ClassB 构造函数========="); } }
package simple.demo; /** * @author Administrator * @date 2019/01/03 */ public class ClassC extends ClassA{ ClassB classB3 = new ClassB(); static { System.out.println("ClassC static========="); } public ClassC(){ System.out.println("ClassC 构造函数========="); } }
package simple.demo; /** * @author Administrator * @date 2019/01/03 */ public class Test { public static void main(String[] args){ ClassC classC = new ClassC(); } }
如果没有看结果,你能猜想输出什么 吗?
输出结果为:
ClassA static========= ClassB static========= ClassB 构造函数========= ClassC static========= ClassB 构造函数========= ClassA 构造函数========= ClassB 构造函数========= ClassC 构造函数=========
分析:
1、执行main方法的 ClassC classC = new ClassC(); 要实例化ClassC必须先加载ClassC,因为ClassC继承于ClassA,所以加载ClassC之前先加载ClassA,所以加载ClassA的时候,就执行ClassA的static块的内容。
先输出: System.out.println("ClassA static=========");
2、输出完1步的内容后,紧接着执行 ClassB classB2 = new ClassB(); 要实例化ClassB必须要先加载ClassB,所以ClassB的static块里面的内容要执行:System.out.println("ClassB static=========");
3、输出完2步的内容后,就要实例化ClassB了,所以执行ClassB的构造函数:System.out.println("ClassB 构造函数=========");
4、输出完3步的内容后,ClassA已经加载完毕,就应该加载ClassC了,所以输出:System.out.println("ClassC static=========");
5、输出完4步的内容后,ClassC已经加载完毕,就应该实例化ClassC了,要实例化ClassC就必须得先实例化ClassA, 因为子类的构造方法都会调用父类的构造方法。实例化ClassA之前必须先获取ClassA的所有属性,所以执行 ClassB classB1 = new ClassB();
6、 要执行ClassB classB1 = new ClassB(),必须先加载ClassB,因为ClassB已经在第2步的时候加载过,所以static快的内容不会再执行,只会执行ClassB的构造方法,输出:System.out.println("ClassB 构造函数=========");
7、输出完6步的内容后,已经获取了ClassA的所有属性,开始执行ClassA的构造函数了,输出:System.out.println("ClassA 构造函数=========");
8、输出完7步的内容后,ClassA已经实例化完毕,紧接着实例化ClassC,实例化ClassC之前要获取ClassC的所有属性,所要要执行:ClassB classB3 = new ClassB();
9、 要执行ClassB classB3 = new ClassB(),必须先加载ClassB,因为ClassB已经在第2步的时候加载过,所以static快的内容不会再执行,只会执行ClassB的构造方法,输出:System.out.println("ClassB 构造函数=========");
10、最后执行ClassC的构造函数,所以输出:System.out.println("ClassC 构造函数=========");