很难过,昨晚参加了校园宣讲,现场笔试。不幸的是自己没有通过笔试,其中一道选择题是自己之前碰到过很多次但是一直都没有搞明白的。
就是父子类的初始化顺序,比如new一个子类的实例对象,我只知道先执行父类的静态代码和构造函数,在执行子类的静态代码和构造函数。至于,子类的静态代码先执行还是父类的构造函数先执行自己就搞不清楚了,至于成员变量和代码块的执行顺序更是云里雾里。自己基础还是太差。下面自己做了一个demo用来强化一下记忆。
先添加父类的定义:
public class FatherClass { public int i=MemberMethod(); public static int j=StaticMethod(); { System.out.println("父类的代码块1"); } { System.out.println("父类的代码块2"); } static{ System.out.println("父类的静态代码块1"); } static{ System.out.println("父类的静态代码块2"); } public FatherClass() { // TODO Auto-generated constructor stub System.out.println("父类的构造函数"); } private static int staticMethod() { // TODO Auto-generated method stub System.out.println("父类的静态方法"); return 0; } private static int StaticMethod() { // TODO Auto-generated method stub System.out.println("父类的静态成员变量"); return 0; } private int MemberMethod() { // TODO Auto-generated method stub System.out.println("父类的成员变量"); return 0; } }
子类的代码:
public class sonClass extends FatherClass{ public int i=MemberMethod(); public static int j=StaticMethod(); { System.out.println("子类的代码块1"); } { System.out.println("子类的代码块2"); } static{ System.out.println("子类的静态代码块1"); } static{ System.out.println("子类的静态代码块2"); } public sonClass() { // TODO Auto-generated constructor stub System.out.println("子类的构造函数"); } private static int staticMethod() { // TODO Auto-generated method stub System.out.println("子类的静态方法"); return 0; } private static int StaticMethod() { // TODO Auto-generated method stub System.out.println("子类的静态成员变量"); return 0; } private int MemberMethod() { // TODO Auto-generated method stub System.out.println("子类的成员变量"); return 0; }
主方法:
public class MainClass { public static void main(String[] args) { // TODO Auto-generated method stub sonClass son = new sonClass(); //FatherClass son1 = new sonClass(); } }
执行结果:
通过结果,可以看到父子类的初始化过程:
先从父类的静态成员进行初始化的,静态成员包括静态变量和静态代码块。
然后初始化子类的静态成员。
然后是父类的普通成员变量,包括代码普通成员和代码块。‘
再然后是父类的构造函数。
最后是子类的普通成员变量和子类的构造函数。
看到这里我才发现,原来子类的构造函数是最后才初始化。而且,父类的成员变量和父类的构造函数初始化顺序是紧挨着的。
当然啦,网上还有比我总结的更详细的大牛,从jvm层面讲解了为什么初始化顺序是这样的,我就不盗窃人家的成果了,这里把地址贴出来: