欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

对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型参数);

第一篇博客先写简单一点的嘻嘻~