Java继承中构造器的调用原理
xxbbtt 人气:0Java的继承是比较重要的特性,也是比较容易出错的地方,下面这个例子将展示如果父类构造器中调用被子类重写的方法时会出现的情况:
首先是父类:
public class test { void fun(){ System.out.println("test fun()"); } void fun1(){ System.out.println("test fun1()"); } test(){ fun(); fun1(); } public static void main(String[] args) { test t =new test(); } }
这里父类的构造器将调用一个fun方法,main函数的运行结果是:
test fun()
test fun1()
然后是子类:
public class test2 extends test { int i = 2; test2(){ fun(); } void fun(){ System.out.println("test2 fun()"); System.out.println(i); } public static void main(String[] args) { test2 t = new test2(); } }
子类增加了一个字段i并初始化为2,并重写了fun方法,不仅打印的字符串不一样,还加了打印i的功能,构造器和父类一样调用了fun方法。main函数的运行结果是:
test2 fun()
0
test fun1()
test2 fun()
2
通常java的类进行初始化的时候,会先进行父类的初始化,所以会先调用父类的构造器,再进行子类的初始化,调用子类的构造器。
一开始写完代码我以为的结果是:
test fun() test fun1() test2 fun() 2
我以为就算父类的方法被重写了,也会调用自己的方法,但事实告诉我们,父类初始化过程中构造器如果调用了被子类重写的方法,会调用被子类重写的方法。
还有一点,如果子类重写的方法中使用了子类才定义的字段,那这个字段的值将是该字段类型的默认值。
所以类的初始化流程总结(继承相关)就是:
1.为对象(相对的子类,因为父类还可能有父类)分配的存储空间初始化为二进制零。
2.调用父类的构造器,如果调用被覆盖的方法,被覆盖的方法将被调用,如果使用了子类中才定义的字段,该字段的值为该字段类型的默认值。
3.调用子类的构造器。
(这里总结的初始化流程只总结了继承相关的,正常的static部分、初始化代码还是正常的样子)
加载全部内容