一、super关键字的使用 1. 为什么需要super? 举例1:子类继承父类以后,对父类的方法进行了重写,那么在子类中,是否还可以对父类中被重写的方法进行调用? 可以! 举例2:子类继承父类以后,发现子类和父类中定义了同名的属性,是否可以在子类中区分两个同名的属性? 可以! 如何调用? 使用super关键字即可。 2. super的理解:父类的 3. super可以调用的结构:属性、方法、构造器 具体的: 3.1 super调用属性、方法 子类继承父类以后,我们就可以在子类的方法或构造器中,调用父类中声明的属性或方法。(满足封装性的前提下) 如何调用呢?需要使用"super."的结构,表示调用父类的属性或方法。 一般情况下,我们可以考虑省略"super."的结构。但是,如果出现子类重写了父类的方法或子父类中出现了同名的属性时, 则必须使用"super."的声明,显式的调用父类被重写的方法或父类中声明的同名的属性。 举例1:子类继承父类以后,对父类的方法进行了重写,那么在子类中,是否还可以对父类中被重写的方法进行调用? 可以!
package chapter07_oop2.src.com.atguigu05._super; /** * ClassName: Person * Description: * * @Author 尚硅谷-宋红康 * @Create 9:08 * @Version 1.0 */ public class Person { //属性 String name; //方法 public void eat(){ System.out.println("人吃饭"); } public void sleep(){ System.out.println("人睡觉"); } }
package chapter07_oop2.src.com.atguigu05._super; /** * ClassName: Student * Description: * * @Author 尚硅谷-宋红康 * @Create 9:08 * @Version 1.0 */ public class Student extends Person { String school; public void study(){ System.out.println("学生学习"); } public void eat(){ System.out.println("学生应该多吃有营养的食物"); } public void sleep(){ System.out.println("学生保证每天不低于10小时的睡眠"); } public void show(){ eat(); //省略了this this.eat(); super.eat(); } }
package chapter07_oop2.src.com.atguigu05._super; /** * ClassName: StudenTest * Package: chapter07_oop2.src.com.atguigu05._super * Description: * * @Author 小白 * @Create 2024/4/2 11:14 * @Version 1.0 */ public class StudenTest { public static void main(String[] args) { Student s1 = new Student(); s1.eat(); s1.sleep(); s1.show(); } }
如果子类没有重写父类中的方法 如果父类还是没有找到 就会找到Object 如果Object还是没有找到 则报错
举例2:子类继承父类以后,发现子类和父类中定义了同名的属性,是否可以在子类中区分两个同名的属性? 可以!
现在是有五个属性
package chapter07_oop2.src.com.atguigu05._super; /** * ClassName: Person * Description: * * @Author 尚硅谷-宋红康 * @Create 9:08 * @Version 1.0 */ public class Person { //属性 String name; private int age; int id = 1001; //身份证号 //方法 public void eat(){ System.out.println("人吃饭"); } public void sleep(){ System.out.println("人睡觉"); } public void doSport(){ System.out.println("人运动"); } }
package chapter07_oop2.src.com.atguigu05._super; /** * ClassName: Student * Description: * * @Author 尚硅谷-宋红康 * @Create 9:08 * @Version 1.0 */ public class Student extends Person { String school; int id = 1002; //学号 public void study(){ System.out.println("学生学习"); } public void eat(){ System.out.println("学生应该多吃有营养的食物"); } public void sleep(){ System.out.println("学生保证每天不低于10小时的睡眠"); } public void show(){ eat(); //省略了this this.eat(); super.eat(); } public void show1(){ doSport(); this.doSport(); super.doSport(); } public void show2(){ System.out.println(id); //1002 找最近 System.out.println(this.id);//1002 找最近 System.out.println(super.id); //1001 找父类的属性 } }
package chapter07_oop2.src.com.atguigu05._super; /** * ClassName: StudenTest * Package: chapter07_oop2.src.com.atguigu05._super * Description: * * @Author 小白 * @Create 2024/4/2 11:14 * @Version 1.0 */ public class StudenTest { public static void main(String[] args) { Student s1 = new Student(); s1.eat(); s1.sleep(); s1.show(); s1.doSport(); s1.show2(); } }
总结:加不加super 区别在于有没有同名 如果没有同名 结果都是一样的
3.2 super调用构造器 ① 子类继承父类时,不会继承父类的构造器。只能通过“super(形参列表)”的方式调用父类指定的构造器。
举例:
package chapter07_oop2.src.com.atguigu05._super; /** * ClassName: Person * Description: * * @Author 尚硅谷-宋红康 * @Create 9:08 * @Version 1.0 */ public class Person { //属性 String name; private int age; int id = 1001; //身份证号 public Person() { System.out.println("Person()...."); } public Person(String name, int age) { this.name = name; this.age = age; } public Person(String name, int age, int id) { this.name = name; this.age = age; this.id = id; } //方法 public void eat(){ System.out.println("人吃饭"); } public void sleep(){ System.out.println("人睡觉"); } public void doSport(){ System.out.println("人运动"); } }
package chapter07_oop2.src.com.atguigu05._super; /** * ClassName: Student * Description: * * @Author 尚硅谷-宋红康 * @Create 9:08 * @Version 1.0 */ public class Student extends Person { String school; int id = 1002; //学号 public void study(){ System.out.println("学生学习"); } public void eat(){ System.out.println("学生应该多吃有营养的食物"); } public void sleep(){ System.out.println("学生保证每天不低于10小时的睡眠"); } public void show(){ eat(); //省略了this this.eat(); super.eat(); } public void show1(){ doSport(); this.doSport(); super.doSport(); } public void show2(){ System.out.println(id); //1002 找最近 System.out.println(this.id);//1002 找最近 System.out.println(super.id); //1001 找父类的属性 } //测试super调用父类的构造器 public Student(){ super(); System.out.println("Student()..."); } }
package chapter07_oop2.src.com.atguigu05._super; /** * ClassName: StudenTest * Package: chapter07_oop2.src.com.atguigu05._super * Description: * * @Author 小白 * @Create 2024/4/2 11:14 * @Version 1.0 */ public class StudenTest { public static void main(String[] args) { Student s1 = new Student(); s1.eat(); s1.sleep(); s1.show(); s1.doSport(); s1.show2(); //************************ System.out.println(); Student s2 = new Student(); } }
② 规定:“super(形参列表)”,必须声明在构造器的首行。
③ 我们前面讲过,在构造器的首行可以使用"this(形参列表)",调用本类中重载的构造器, 结合②,结论:在构造器的首行,"this(形参列表)" 和 "super(形参列表)"只能二选一。
④ 如果在子类构造器的首行既没有显示调用"this(形参列表)",也没有显式调用"super(形参列表)", 则子类此构造器默认调用"super()",即调用父类中空参的构造器。
⑤ 由③和④得到结论:子类的任何一个构造器中,要么会调用本类中重载的构造器,要么会调用父类的构造器。只能是这两种情况之一。
⑥ 由⑤得到:一个类中声明有n个构造器,最多有n-1个构造器中使用了"this(形参列表)", 则剩下的那个一定使用"super(形参列表)"。
--> 我们在通过子类的构造器创建对象时,一定在调用子类构造器的过程中,直接或间接的调用到父类的构造器。 也正因为调用过父类的构造器,我们才会将父类中声明的属性或方法加载到内存中,供子类对象使用。