最近在做面试题时遇到了一道关于子父类的初始化话顺序的问题,因为不是很熟悉,没有答对,下去仔细研究了下,发现真的有好多知识点。先说总结和代码,最后解释说明。
父类静态变量----》父类静态代码块----》子类静态变量----》子类静态代码块----》初始化父类成员变量----》父类构造函数------》初始化子类成员变量----》子类构造函数。
public class TestStatic
{
public static void main(String[] args)
{
new Z();
}
}
class F
{
private static String i = "F static";
static{
System.out.println(i);
}
private String j = fun();
public String fun(){
System.out.println("F fun ");
return "F fun ";
}
F(){
System.out.println("F constractor");
}
}
class Z extends F
{
private static String i = "Z static";
static{
System.out.println(i);
}
private String j = fun();
public String fun(){
System.out.println("z fun ");
return "z fun ";
}
Z(){
System.out.println("Z constractor");
}
}
但是需要注意,当子类函数与父类函数构成覆盖时,调用的亦然是子类的函数,代码运行结果如下:
当将上面代码,去掉覆盖效果,结果如下:
当没有继承关系存在时:
静态变量----》静态代码块-----》成员变量----》构造代码块-----》构造函数。
总结:
按照我的理解,java在new Z()时候,应该是先将Z类加载进JVM,然后发现Z拥有父类,那么需要再加载F类进来,但是静态变量属于类的,随着类的加载而初始化,所以静态变量优先执行没有问题,静态代码块也是属于类,所以静态代码块优先于成员变量。由于子类构成了覆盖的话,那么父类方法中fun就不存在了,只有一个子类的fun,所以调用的只能是子类的fun.然后构造器的话,必定是父类的优先于子类。因为在子类的无参构造器第一行会有隐式的super()。
以上总结,是我的观点,不一定全部正确,欢迎大家和我讨论。