对Java中构造方法调用顺序的理解
程序员文章站
2022-05-14 09:25:02
...
之前对构造函数的调用顺序一直很迷,只知道很死板地记着“父类构造函数先于子类构造函数调用”,但是其中的原因并没有去深究。前几周大概看了一遍JAVA编程思想,真的是博大精深……但是对这个概念起码有了一点自己的看法。欢迎指正哦~
class Fu{
}
class Zi extends Fu{
}
public class Demo1 {
public static void main(String[] args) {
Fu fu = new Fu();
Zi zi = new Zi();
}
}
上面这段代码是可以运行起来的,虽然它没有任何实际的用处。但是,我们应该能想到,编译器为我们做了一些事情,首先,类是一定会有构造方法的。如果你没写,编译器就会自动创建一个默认构造方法。默认构造方法不带任何参数,也没有方法的实体。
修改一下代码,在子类中写一个无参构造方法。
class Fu{
}
class Zi extends Fu{
Zi(){
System.out.println("子类的无参构造方法");
}
}
public class Demo1 {
public static void main(String[] args) {
Fu fu = new Fu();
Zi zi = new Zi();
}
}
运行结果:
子类的无参构造方法
这里应该无需解释了吧。
那么,进入正题。为什么先执行父类的构造方法呢?
答案就是:super()!!!
继承的规则就是:子类的构造方法中,第一行代码应该是super语句。如果没有显式地写出来,就会自动加上一个super()。所以上面的代码可以理解为:
class Fu{
/*
* Fu(){}; //编译器自动生成的默认构造方法
*/
}
class Zi extends Fu{
Zi(){
//super(); //编译器自动调用无参的父类构造方法
System.out.println("子类的无参构造方法");
}
}
public class Demo1 {
public static void main(String[] args) {
Fu fu = new Fu();
Zi zi = new Zi();
}
}
其实总的来说,执行Zi zi = new Zi()时,还是会先进入子类的构造方法中,只不过由于第一行代码就是super(),等于先调用父类的无参构造方法。所以就有了“先执行父类构造,在执行子类构造方法”这一说,但我们应该清楚,调用的入口,其实是该类本身,而不是它的父类啥的……
下面这段代码,我想你应该能很快地找出问题所在:
class Fu{
Fu(int age){
System.out.println("父类的构造方法");
}
}
class Zi extends Fu{
Zi(){
System.out.println("子类的无参构造方法");
}
}
public class Demo1 {
public static void main(String[] args) {
Zi zi = new Zi();
}
}
我们显式地为父类写了一个有参构造方法,此时编译器不会再为父类生成无参构造方法。当声明一个子类对象并且获得实例时,会调用其构造方法,子类构造方法第一行默认为super(),也就是调用父类的无参构造方法,但是父类并没有无参构造方法,所以会报错。
解决办法就是:再为父类重载一个无参构造方法,或者是在子类构造方法的第一行显式地加上一行代码:
super(int型参数);
第一篇博客先写简单一点的嘻嘻~