一、关键字super的使用
1、为什么需要super?
举例1:子类继承父类以后,对父类的方法进行了重写,那么在子类中,是否还可以对父类中被重写的方法进行调用?
举例2:子类继承父类以后,发现子类和父类中定义了同名的属性,是否可以在子类中区分两个同名的属性?
super的理解:父类的
2、子类调属性和方法
super可以调:属性、方法、构造器
- 子类继承父类以后,我们就可以在子类的方法或者构造器中,调用父类中声明的属性和方法。(满足封装性的前提下),调用时,需要使用”super.“的结构,表示调用父类的属性或者方法。
- 一般情况下,我们可以省略super.的结构。但是,如果出现子类重写了父类的方法或者子父类中出现了同名的属性时,则必须使用super.的结构,显示的调用父类被重写的方法或父类中声明的同名的属性。
package _super;
/**
* package:atguigu03_extends
*
* @Author jimmy-yan
* @Create 2024/10/16 16:30
*/
public class Person {
String name;
int age;
public void eat() {
System.out.println("Person吃饭");
}
public void sleep() {
System.out.println("Person睡觉");
}
public void sport(){
System.out.println("运动");
}
}
package _super;
/**
* package:atguigu03_extends
*
* @Author jimmy-yan
* @Create 2024/10/16 16:30
*/
public class Student extends Person {
String school;
public void eat() {
System.out.println("Student吃饭");
}
public void sleep() {
System.out.println("Student睡觉");
}
public void show(){
eat(); //省略了eat Student吃饭
this.eat(); //todo Student吃饭 直接在本地找
super.eat(); //todo Person吃饭 滤过了当前类,直接到父类中找
}
public void show1(){
sport();
this.sport();
}
}
package _super;
/**
* package:_super
*
* @Author jimmy-yan
* @Create 2024/10/24 16:50
*/
public class StudentTest {
public static void main(String[] args) {
Student s1 = new Student();
s1.eat(); //Student吃饭
s1.sleep(); //Student睡觉
s1.show();
}
}
3、子类调构造器
1、子类继承父类时,不会继承父类的构造器。只能通过"super(形参列表)”的方式调用父类指定的构造器。
2、规定:“super(形参列表)”,必须声明在构造器的首行。
3、我们前面讲过,在构造器的首行可以使用"this(形参列表)",调用本类中重载的构造器,
结合②,结论:在构造器的首行,"this(形参列表)"和"super(形参列表)"只能二选一。
4、如果在子类构造器的首行既没有显示调用"this(形参列表)“,也没有显式调用"super(形参列表)”,
则子类此构造器默认调用"super()",即调用父类中空参的构造器。
5、由③和④得到结论。子类的任何一个构造器中,要么会调用本类中重载的构造器,要么会调用父类的构造器。只能是这两种情况之一。
6、由⑤得到:一个类中声明有n个构造器,最多有n-1个构造器中使用了"this(形参列表)“,则剩下的那个一定使用"super(形参列表)”。
我们在通过子类的构造器创建对象时,一定在调用子类构造器的过程中,直接或间接的调用到父类的构造器。
也正因为调用过父类的构造器,我们才会将父类中声明的属性或方法加载到内存中,供子类对象使用。
二、子类对象实例化全过程
1、从结果的角度来看:体现为类的继承性
当我们创建子类对象后,子类对象就获取了其父类中声明的所有的属性和方法,在权限允许的情况下,可以直接调用
2、从过程的角度来看:
当我们通过子类的构造器创建对象时,子类的构造器一定会直接或间接的调用到其父类的构造器,而其父类的构造器同样会直接或间接的调用到其父类的父类的构造器…,直到调用了Object类中的构造器为止。
正因为我们调用过子类所有的父类的构造器,所以我们就会将父类中声明的属性、方法加载到内存中,供子类的对象使用。
问题:在创建子类对象的过程中,一定会调用父类中的构造器吗? yes!
3.问题:创建子类的对象时,内存中到底有几个对象?
就只有一个对象。即为当前new后面和造器对应的类的对象。|