10.4 构造函数的调用顺序

新声明一个子类对象的时候,会先调用父类的构造函数,再调用子类的构造函数,例如
public class Rectangle{
    protected double length;
    protected double height;
    public Rectangle(){
        System.out.println("Rectangle构造函数调用中");
    }
}
public class Square extends Rectangle{
    public Square(){
        System.out.println("Square构造函数调用中");
    }
}
假如新建一个Square 对象:
public static void main(String[]a){
    Square s=new Square();
}
控制台将打印:
Rectangle构造函数调用中
Square构造函数调用中
一个对象要创建出来,需要从它的最根部的父类开始,就好像金字塔从底部开始,逐层往上。 编译器干预构造函数比较多,在一个对象的构造函数调用的时候,就算没有写,也会首先调用它的父类构造函数。
这里有一个重要原则:子类调用构造函数的时候,如果没有明确调用任何父类构造函数,那么会调用父类的缺省构造函数。
例如上面的例子里Square调用无参数构造函数生成对象s,那么会首先调用父类的无参数构造函数。 所以会有这样的输出。
假如Square有这样的构造函数:
public class Square extends Rectangle{
    public Square(double len){
        System.out.println("Square构造函数2调用中");
        this.height=len;
        this.length=len;
    }
    public static void main(String[]args){
        Square s=new Square(4);
    }
}
还是会先调用 父类Rectangle的缺省构造函数Rectangle()。还是会打印出
Rectangle构造函数调用中
Square构造函数2调用中
如果父类没有缺省构造函数,那么就会报语法错误了!前面一章已经讲解过,如果要取消掉缺省构造函数,就是创建一个带参数的构造函数。假如Rectangle类改成了这样:
public class Rectangle{
    protected double length;
    protected double height;
    public Rectangle(double length,double height){
        System.out.println("Rectangle构造函数调用中");
        this.length=length;
        this.height=height;
    }
}
那么在Square类马上就会显示语法错误了:“未定义隐式超构造函数 Rectangle()。必须显式调用另一个构造函数”。如图所示:

这种情况,可以在Square构造函数里,显式调用父类的构造函数,那就是使用super关键字:
public class Square extends Rectangle{
    public Square(double len){
        super(len,len);
        System.out.println("Square构造函数调用中");
    }
    public static void main(String[]a){
        Square s=new Square(4);
    }
}
或者在Rectangle类添加一个缺省构造函数