-----------------------------------第二次更新----------------------------------
在对java基础复习之后,我对本文末尾的问题有了答案。原来创建子类会先把父类进行加载,但是并不会初始化成对象,只是进行了加载和连接,所以静态代码块会先执行
然后是super()什么时候执行,super()是在子类初始化的过程中执行,因为父类必须先初始化,所以说super()会在子类的构造器调用的过程中,是过程中,也就是说此时子类还没完成初始化。刚好过程中初始化父类,所以从顺序上看
父类是先完成初始化,子类再完成初始化,这也与super()在子类构造器第一行代码的硬性要求相吻合,不得不说开发人员的语法设计还是很精妙的
------------------------------------
首先我们要明确的两个java语法规定是
1.执行顺序:静态代码块>普通代码块>构造方法
2.子类的构造过程中必须调用父类的构造方法
先上代码,我们再一步步分析
class Father{ public Father(){ System.out.println("1111111"); } { System.out.println("2222222"); } static{ System.out.println("3333333"); } } class Son extends Father{ public Son(){ //super(); System.out.println("4444444"); } { System.out.println("5555555"); } static { System.out.println("6666666"); } } public class MethodOrderTest { public static void main(String[] args) { new Son(); } }
在不执行以上代码的时候我们来分析输出结果
1.本类编译,然后在编译两个从类的时候,Father类先编译,Son类后编译,所以静态代码块输出顺序1:3333333最先输出,之后是输出顺序2:6666666
2.开始执行new Son(),
这个时候就有一个疑问了,根据第2个java语法我们知道super()这个隐含方法是存在于子类的构造器中的,我在代码中也通过注释表达出来了,于是一开始的我认为既然存在super(),并且看了很多人的博客写的都是super()方法是调用父类构造器的
这样一来我就觉得应该是执行Son这个子类,等执行到super()的时候再创建父类,那么按照第一个java语法可知应该输出的是输出顺序3:5555555
之后执行到Son的构造器,先执行super(),如下,那么应该为输出顺序4:2222222,接着输出顺序5:1111111
public Son(){ //super(); System.out.println("4444444"); }
最后置信Son构造器的最后一行代码,输出顺序6:4444444
---------------------------------------------------------------分割线-------------------------------------------------------------
然而实际正确的输出顺序是
3333333 6666666 2222222 1111111 5555555 4444444
可以看到从输出顺序3就已经出错了,那么这是为什么呢,按照super()的定义来说没有问题,的确是调用父类构造器创建父类对象,而且super()的执行顺序也没有问题,在构造器中就是低于普通代码块和静态代码块执行的
为了解决上面的疑问,我看了一些博客,但是可能是关键词搜索不对,所以并没有找到满意的答案
-------------------------------------------------------------------------------------------------------------------------------------------------------
于是根据我的理解和面试题的解释,我写出想法总结如下:
子类在创建的时候会先创建父类对象,可能是通过super()创建(因为不确定我只能用可能来形容)
但是创建的优先级是优于子类的创建代码,意思就是想要创建子类的Class对象,必须先创建父类的Class对象,无关super()这行代码的位置和执行顺序
综上
留下一个问题,super()到底啥时候执行,希望有人能告知一下