我们可以在子类的构造器中,通过super关键字调用父类的构造器。
// 父类
class Person {
private String name;
public Person() {
}
}
// 子类
class Man extends Person{
private int age;
public Man() {
super(); // 调用了父类的空参构造器
}
}
我们接下来谈谈其中需要我们注意的地方。
1.如果在子类没有显式的调用父类构造器(也就是没有在子类的构造器中写super()语句),子类会默认调用父类的空参构造器。
// 父类的构造器中有一条输出语句
class Person {
private String name;
public Person() {
System.out.println("我是父类");
}
}
class Man extends Person{
private int age;
// 子类构造器中没有显式的调用父类构造器
public Man() {
}
public static void main(String[] args) {
Man man = new Man();
}
}
运行结果:
我是父类
我们可以看到,子类Man中并没有显式的调用父类Person的构造器,但是却执行了父类空参构造器中的输出语句,那是因为在将Man.java文件编译成Man.class文件时,已经给Man中的构造器中添加了super()语句。
那我们可能会想,如果父类没有空参构造器呢?
// 父类中没有空参构造器
class Person {
private String name;
public Person(String name) {
this.name = name;
}
}
class Man extends Person{
private int age;
public Man() {
}
}
没错,这样就会报错了。Eclipse中的错误信息===》“Implicit super constructor Person() is undefined. Must explicitly invoke another constructor” (隐式构造函数Person()是未定义的。必须显式调用另一个构造函数)
解决方法:
方法一:
在父类中定义一个空参构造器。
class Person {
private String name;
// 父类的空参构造器
public Person() {
}
// 父类参数为name的构造器
public Person(String name) {
this.name = name;
}
}
class Man extends Person{
private int age;
// 默认会调用父类中的空参构造器
public Man() {
}
}
方法二:
细心的朋友会发现,前面的错误信息中有这样一句话(必须显式的调用另一个构造器),也就是说父类当中没有空参构造器,我们需要显式的调用父类的其他构造器。
// 父类中没有空参构造器
class Person {
private String name;
public Person(String name) {
this.name = name;
}
}
class Man extends Person{
private int age;
public Man() {
super("Tom"); // 显式的调用父类中参数为name的构造器
}
}
建议:我们在定义类时,都给它定义空参构造器
2.“super(形参列表)” 一定要是构造器中的第一条语句。
这个规则和this(“形参列表”)类似,就不多说了。因为它们两个都要是构造器中的第一条语句,所以一个构造器中,只能显式的调用一个。
大家可能会有一个疑问,子类为什么就一定要调用父类的构造器啊?
这是为了确保给子类当中的所有属性都能初始化。如果父类中的属性是私有的(如Person中的name属性)那么子类是无法显式的对它进行初始化赋值的,那么只能通过父类中的构造器对它进行赋值。所以子类就一定要调用父类的构造器。
加油!!💪