1. 父类,子类均没有提供构造函数 => 编译器会分别为父类,子类生成一个默认的无参数的构造函数
  2. 父类没有提供构造函数,子类提供无参数构造函数 => 子类构造函数无需super()
class Father {

}
class Child extends Father {
    Child() {
        System.out.println("这是子类的无参数构造函数");
    }
}
public class Main {

    public static void main(String[] args) {
        new Child();
    }

}

输出:这是子类的无参数构造函数
3. 父类没有提供构造函数,子类提供有参数构造函数 => 子类构造函数无需super()

class Father {

}
class Child extends Father {
    Child(int age) {
        System.out.println("这是子类的有参数构造函数");
    }
}
public class Main {

    public static void main(String[] args) {
        new Child(1);
    }

}

输出:这是子类的有参数构造函数
4. 父类提供无参数构造函数,子类提供无参数构造函数 => 子类构造函数无需super()且子类实例化时,先执行父类的无参数构造函数,再执行子类的无参数构造函数

class Father {
    Father() {
        System.out.println("这是父类的无参数构造函数");
    }
}
class Child extends Father {
    Child() {
        System.out.println("这是子类的无参数构造函数");
    }
}
public class Main {

    public static void main(String[] args) {
        new Child();
    }

}

输出:这是父类的无参数构造函数
这是子类的无参数构造函数
5. 父类提供无参数构造函数,子类提供有参数构造函数 => 子类构造函数无需super()且子类实例化时,先执行父类的无参数构造函数,再执行子类的有参数构造函数

class Father {
    Father() {
        System.out.println("这是父类的无参数构造函数");
    }
}
class Child extends Father {
    Child(int age) {
        System.out.println("这是子类的有参数构造函数");
    }
}
public class Main {

    public static void main(String[] args) {
        new Child(1);
    }

}

输出:这是父类的无参数构造函数
这是子类的有参数构造函数
6. 父类提供有参数构造函数,子类不能提供无参数构造函数
7. 父类提供有参数构造函数,子类提供有参数构造函数 => 子类构造函数需要super()且子类实例化时,先执行父类的有参数构造函数,再执行子类的有参数构造函数

class Father {
    Father(int age) {
        System.out.println("这是父类的有参数构造函数");
    }
}
class Child extends Father {
    Child(int age) {
        super(age);
        System.out.println("这是子类的有参数构造函数");
    }
}
public class Main {

    public static void main(String[] args) {
        new Child(1);
    }

}

输出:这是父类的有参数构造函数
这是子类的有参数构造函数
8. 父类既提供无参数构造函数,又提供有参数构造函数 => 子类构造函数无需super()且子类实例化时,先执行父类的无参数构造函数,再执行子类的无参数构造函数

class Father {
    Father() {
        System.out.println("这是父类的无参数构造函数");
    }
    Father(int age) {
        System.out.println("这是父类的有参数构造函数");
    }
}
class Child extends Father {
    Child() {
        System.out.println("这是子类的无参数构造函数");
    }
}
public class Main {

    public static void main(String[] args) {
        new Child();
    }

}

输出:这是父类的无参数构造函数
这是子类的无参数构造函数

class Father {
    Father() {
        System.out.println("这是父类的无参数构造函数");
    }
    Father(int age) {
        System.out.println("这是父类的有参数构造函数");
    }
}
class Child extends Father {
    Child(int age) {
        System.out.println("这是子类的有参数构造函数");
    }
}
public class Main {

    public static void main(String[] args) {
        new Child(1);
    }

}

输出:这是父类的无参数构造函数
这是子类的有参数构造函数

class Father {
    Father() {
        System.out.println("这是父类的无参数构造函数");
    }
    Father(int age) {
        System.out.println("这是父类的有参数构造函数");
    }
}
class Child extends Father {
    Child(int age) {
        super(age);
        System.out.println("这是子类的有参数构造函数");
    }
}
public class Main {

    public static void main(String[] args) {
        new Child(1);
    }

}

输出:这是父类的有参数构造函数
这是子类的有参数构造函数

总结:
1. 父类没有提供构造函数,或者父类提供了无参构造函数,那么子类无需考虑super()
2. 只要父类中只存在有参数构造函数,那么子类必须考虑super()