下面是一个将这三个类放在同一个文件中的示例:
public class Test {
public static void main(String[] args) {
Student s1 = new Student();
}
}
class Student extends Person {
public Student() {
System.out.println("Student()无参构造器后执行了");
super(); // 实际上这行代码是隐式的,但显式写出可以增加代码可读性
}
}
class Person {
public Person() {
System.out.println("Person()无参构造器先执行");
}
}
- 我将
Student
和Person
类定义为非public
的,因为在一个文件中只能有一个public
类,并且它的名称必须与文件名相同。如果你希望它们都是public
的,你需要将它们放在不同的文件中。 - 我添加了
super();
在Student
的构造器中。虽然它是隐式调用的(如果父类没有提供其他构造器),但显式地写出它可以增加代码的可读性。 - 类之间用空行分隔,以提高代码的可读性。这不是必须的,但通常是个好习惯。
我们来看看输出结果:
Person()无参构造器先执行
Student()无参构造器后执行了
为什么先输出了“Person()无参构造器先执行”
在Java中,当你创建一个子类的实例时,如果子类构造函数没有显式地调用父类的构造函数,那么编译器会自动插入一个对父类无参构造函数的调用(如果父类中存在这样的构造函数)。这是Java中构造函数链式调用的一个基本规则,确保父类在子类之前被正确初始化。
当你创建Student
类的实例时new Student()
,会首先调用Student
的构造函数。但是,由于Student
类继承了Person
类,所以在Student
的构造函数执行之前,编译器会自动先调用Person
类的无参构造函数(如果存在)。这就是为什么首先输出了"Person()无参构造器先执行"。
在Student
的构造函数内部,你输出了"Student()无参构造器后执行了",这是在Person
的构造函数执行之后发生的。因此,整个输出顺序是先父类后子类。
这个过程是Java中对象初始化的一个重要部分,确保在子类访问或修改从父类继承的任何状态之前,父类已经完成了其自己的初始化。