水光潋滟晴方好,山色空蒙雨亦奇。
欲把西湖比西子,浓妆淡抹总相宜。—-宋代苏轼《饮湖上初晴后雨二首·其二》


子类实例化时总是先调用父类的无参构造方法

子类继承父类时,会继承父类的非私有成员变量和方法。子类实例化时,必须执行父类一系列的初始化工作,如果有多个间接父类,从最初的那个父类执行,这样,子类才能够拥有父类的成员变量和方法。

示例一

父类:Father 子类:Son

Father.java

//package com;

public class Father {
    private String name = "FATHER";

    public Father() {
        whoAmI();
        tellName(name);
    }
    public void whoAmI() {
        System.out.println("Father says, I am " + name);
    }

    public void tellName(String name) {
        System.out.println("Father's name is " + name);
    }

    public static void main(String[] args) {
        Father f = new Father();

    }
}

父类的执行结果:

Father says, I am FATHER
Father's name is FATHER

Son.java

//package com;

public class Son extends Father {
    private String name = "SON";

    public Son() {  
        whoAmI();
        tellName(name);     
    }

    public void whoAmI() {
        System.out.println("Son says, I am " + this.name);
        // 执行父类构造方法时,this.name(Son的变量)还没有初始化
    }

    public void tellName(String name) {
        System.out.println("Son's name is " + name);
    }

    public static void main(String[] args) {
        Son s = new Son();
    }
}

子类执行结果:

Son says, I am null
Son's name is FATHER
Son says, I am SON
Son's name is SON

从子类的结果中,可以看出,子类实例化时,执行了父类的无参构造方法,然而父类无参构造函数的构造方法里执行的方法 whoAmI() 和 tellName() 被子类重写

这是Father类默认构造函数调用时的输出:

Son says, I am null
Son's name is FATHER

this.name 为空,是因为,this指向 Son 类的变量,而这个时候,Son 类的还没有初始化,name 值为null。
而输出的 FATHER 则 Father 类的成员变量。

示例二

在 Father 类默认构造函数上增加调用 say() 方法。
Father.java

//package com;

public class Father {
    private String name = "FATHER";

    public Father() {
        whoAmI();
        tellName(name);
        say();
    }

    public void whoAmI() {
        System.out.println("Father says, I am " + name);
    }

    public void tellName(String name) {
        System.out.println("Father's name is " + name);
    }

    public void say(){
        System.out.println("父类方法 say() ");
    }

    public static void main(String[] args) {
        Father f = new Father();

    }
}

父类的执行结果:

Father says, I am FATHER
Father's name is FATHER
父类方法 say()

Son.java

package com;

public class Son extends Father {
    private String name = "SON";

    public Son() {
        whoAmI();
        tellName(name);     
    }

    public void whoAmI() {
        System.out.println("Son says, I am " + this.name);

    }

    public void tellName(String name) {
        System.out.println("Son's name is " + name);
    }

    public static void main(String[] args) {
        Son s = new Son();
    }
}

子类的执行结果:

Son says, I am null
Son's name is FATHER
父类方法 say() 
Son says, I am SON
Son's name is SON

从上面的结果可以清楚看到,Father 类执行默认构造方法时,调用了没有被 Son 类重写的 say() 方法。

示例三

删除 Father 类的无参构造方法,Son 类必须 super 显示调用父类的构造方法。
否则报错

Implicit super constructor Father() is undefined. Must explicitly invoke another constructor(隐式的 super() 构造函数 father() 是未定义的。必须显式调用另一个构造函数)

子类都有 隐式的super() 调用父类的默认的构造方法,尽管你没有写 super(),也是隐式存在。

Father.java

//package com;

public class Father {
    private String name = "FATHER";

    public Father(int i){
        System.out.println("父类的有参构造方法");
    }

    public void whoAmI() {
        System.out.println("Father says, I am " + name);
    }

    public void tellName(String name) {
        System.out.println("Father's name is " + name);
    }

    public void say(){
        System.out.println("父类方法 say() ");
    }

    public static void main(String[] args) {
        Father f = new Father(1);

    }
}

Son.java

//package com;

public class Son extends Father {
    private String name = "SON";

    public Son() {
    /*当父类没有默认的构造方法时,
     必须显示调用父类的方法*/  
        super(2);
        whoAmI();
        tellName(name);     
    }

    public void whoAmI() {
        System.out.println("Son says, I am " + this.name);

    }

    public void tellName(String name) {
        System.out.println("Son's name is " + name);
    }

    public static void main(String[] args) {
        Son s = new Son();
    }
}

Son 类执行的结果:

父类的有参构造方法
Son says, I am SON
Son's name is SON