一、子类对象的实例化过程
在继承的操作中,子类对象在实例化之前必须首先调用父类中的构造方法,再调用子类自己的构造方法
就如同和实际生活中肯定是先有父母之后才能有孩子,孩子不可能凭空“蹦”出来,对于程序也是一样,之所以会调用父类中的构造方法,就是要用父类的构造方法为父类中的属性初始化,就表示先有父类实例,然后才能产生子类实例。
class Person{
private String name;
private int age;
public Person(){
System.out.println("父类 Person 中的构造"); // 父类的构造方法
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
}
class Student extends Person{
// Student 是 Person 的子类
private String school;
public Student(){
System.out.println("子类 Student 中的构造");
}
public String getSchool(){
return school;
}
public void setSchool(String school){
this.school = school; // 设置 school 属性
}
}
public class Test{
public static void main(String[] args) {
Student stu = new Student();
stu.setName("张三"); //此时访问的方法是父类的,子类中并没有定义
stu.setAge(30);
stu.setSchool("Jialidun"); // 此时的方法是在子类中定义的
System.out.println("姓名:"+stu.getName()+",年龄:"+stu.getAge() +",学校:" + stu.getSchool());
}
}
运行结果可以清楚发现,子类对象在实例化前会默认调用父类中的构造方法
实际对于以上的代码实际在子类中的构造方法中隐含了 super()
的语法:
class Student extends Person{
// Student 是 Person 的子类
private String school;
public Student(){
super(); // 加与不加此语句效果相同
System.out.println("子类 Student 中的构造");
}
public String getSchool(){
return school;
}
public void setSchool(String school){
this.school = school; // 设置 school 属性
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
二、方法的覆写
所谓的方法覆写就是指子类定义了与父类中同名的方法,但是在方法覆写时必须考虑到权限,即被子类覆写的方法不能拥有比父类方法更加严格的访问权限
// 访问权限范围
public > default > private
- 1
- 2
class Person{
void print(){
System.out.println("Person --> void print");
}
}
class Student extends Person{
// Student 是 Person 的子类
public void print(){ // 覆写父类中的方法,扩大了权限
System.out.println("Student --> void print");
}
}
public class Test{
public static void main(String[] args) {
new Student().print(); // 此处执行的是被覆写过的方法
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
此处Student子类中定义了与 Person 父类中同名的方法,但是在子类中此方法的访问权限被扩大了,符合覆写的概念,当方法被覆写之后,子类对象调用的将是被覆写后的方法
方法覆写时从 private 变为 default 不算是方法覆写
class Person{
private void print(){
System.out.println("Person --> void print");
}
public void fun(){
this.print(); // 通过定义的 fun 方法调用 print()
}
}
class Student extends Person{
// Student 是 Person 的子类
void print(){ // 覆写父类中的方法,扩大了权限
System.out.println("Student --> void print");
}
}
public class Test{
public static void main(String[] args) {
new Student().fun(); // 此处执行的是被覆写过的方法
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
此处并没有被覆写,而是在子类中重新定义了一个新的方法
方法的重载和覆写的区别:
三、super 关键字的作用
使用 super 关键字可以从子类中调用父类中的构造方法、普通方法和属性,与this 调用构造方法一样,语句必须放在子类构造方法的首行
class Person{
private String name;
private int age;
public Person(String name,int age){
this.setName(name);
this.setAge(age);
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
public String getInfo(){
return "姓名:" + this.getName() + "; 年龄:" + this.getAge();
}
}
class Student extends Person{
// Student 是 Person 的子类
private String school;
public Student(String name,int age,String school){
super(name,age); // 指定调用父类中的构造方法
this.setSchool(school);
}
public String getSchool(){
return school;
}
public void setSchool(String school){
this.school = school; // 设置 school 属性
}
public String getInfo(){
return super.getInfo() + ";学校:" + this.getSchool(); // 扩充父类中的方法
}
}
public class Test{
public static void main(String[] args) {
Student stu = new Student("张三",30,"Jialidun");
System.out.println(stu.getInfo()); // 打印信息,调用覆写过的方法
}
}
- 44
- 45
- 46
- 47
- 48
程序中的子类使用 super() 的形式调用了父类中两个参数的构造方法,然后在子类中又覆写了父类中的 getInfo() 方法,所以输出的内容是被子类覆写过的内容。
this 与 super 的区别: