总的调用顺序是先静态,后动态;先父类,后子类;先成员,后自身。
- 首先是静态资源,包括静态域(常量,变量),静态代码块,按父类——>子类的顺序加载。
- 然后是父类的成员按声明顺序先后调用,其次是父类的构造函数。
- 与第二条相仿,当父类的所有静态成员,动态成员以及构造函数都加载完毕,表明父类已经被完整的构造了,初始化完成了,子类再按照 先成员后自身 的顺序依次加载,需要注意的是最后初始化的一定是子类的构造函数。
这里还是要说明下,实际操作中或者面试中死记硬背是无用的,而且不理解的话也记不久。
java之所以采用这样的调用顺序,是有java本身的原因的。
比如,先加载静态成员,是因为这块资源有单独的内存分配空间,而且静态资源无关类的初始化,只要类存在,静态资源就存在(类的构造方法也是静态的,只不过是隐式调用),当然,静态资源那么多,不可能一次同时加载,也是按照声明顺序,从父类到子类的顺序来依次进行的。
再比如,一定要类中的所有成员都初始化完成才调用构造函数,这是因为构造函数有个作用是检查类中成员是否被正确的初始化。所以我们往往才在构造函数进行各种成员变量的初始化,成员的绑定,事件的绑定等初始化工作。
最后,子类往往能直接使用父类中非private的成员,方法也是基于这样的调用顺序才得以完成的,一个类能调用另一个类中的非静态资源,肯定是这个类已经完全的初始化了,否则调用就会出错,相当于使用未声明变量。
这里,如果理解了上述调用顺序,就可以延展出java中很多的问题,比如方法可以重载,而域,构造方法,静态资源不可重写,就可以从调用顺序的角度来回答,父类中的静态资源、域(常量、变量)、构造方法一经生成,就不可“更改”(不可“更改”不是值不能被更改,而是代码块不能被替换),因为它们已经被放入一块特定的区域了。普通方法由于在类的初始化中并未被调用,所以可以在运行时动态替换,也就是重写。