一、对象的创建过程
- 对象的创建过程和Super配套视频讲解
对象的创建和super
1. 分配内存空间(父类+子类) 2. 初始化父类的属性 3. 调用父类的构造方法 4. 再初始化子类的属性 5. 调用子类的构造方法
遵循先父后子的顺序,如果父类有父类,那么先初始化父类的父类
二、Super
含义:super表示父类对象的引用(this表示当前对象,super表示父类对象)
使用Super可以访问父类的属性和方法
使用时机:当父类的方法或属性被子类覆盖(重写)时,可以使用Super访问父类的属性和方法
访问父类的属性
public class Super { int a=10; //父类熟悉 成员变量 } class Sub extends Super{ int a=20;//成员变量、属性 public void m1(){ int a=30;//局部变量 System.out.println(a); //就近原则,局部变量 System.out.println(this.a); //就是调用本类中的成员变量 System.out.println(super.a); //调用父类的成员变量 } } class TestSub{ public static void main(String[] args) { //1.分配空间 Sub sub = new Sub(); //自动调用构造器 sub.m1(); } }
可以访问父类的方法
package com.baidu.whj; /** * @author Wanghj * @version 1.0 * @date 2022/12/6 20:30 */ public class Super { int a = 10; //父类熟悉 成员变量 public void m1() { int a = 30;//局部变量 System.out.println(a); //就近原则,局部变量 System.out.println(this.a); //就是调用本类中的成员变量 } public void m2() { System.out.println("m2 in super"); } } class Sub extends Super { int a = 20;//成员变量、属性 public void m1() { int a = 30;//局部变量 System.out.println(a); //就近原则,局部变量 System.out.println(this.a); //就是调用本类中的成员变量 System.out.println(super.a); //调用父类的成员变量 } //实现覆盖、重写: 方法名相同,形成列表相同,返回值类型相同,修饰符必须相同或更宽 public void m2() {//覆盖父类的方法 super.m1(); System.out.println("m2 in sub"); } } class TestSub { public static void main(String[] args) { //1.分配空间 Sub sub = new Sub(); //自动调用构造器 sub.m2(); } }
三、多态
多态的视频讲解
java之多态
概念:使用父类引用指向不同的子类对象,不同的子类对象形成不同的形态特点
多态的体现:使用父类引用存储子类对象
class animal{} class Dog extends Animal{} class Cat extends Animal{}
1、特点
子类对象类型始终不变
例子
public class Animal { } class Dog extends Animal { } class Cat extends Animal { } class TestAnimal { public static void main(String[] args) { Dog d = new Dog(); Animal a = d;//将dog对象存储引用到Animal中 System.out.println(d); System.out.println(a); } } /* com.baidu.whj.Dog@135fbaa4 com.baidu.whj.Dog@135fbaa4 */
编译时只能调用引用类型中声明的方法
由于多态的存在,只有在程序运行时才能知道父类中存储的是什么类型,而编译器无法得知,只能确定引用中存储的对象是子类,子类一定会有父类的方法,因此我们只能调用引用类型中声明的方法
Scanner sc=new Scanner(System.in); int n=sc.nextInt(); Animal a1;//编译器无法得知,子类对象的类型 if(n%2==0){ a1=new Fish(); }else{ a1=new Bird(); } //编译器只能确定,调用父类的方法是不存在问题的 a1.eat(); a1.sleep(); a1.fly();
运行时,如果子类覆盖了父类中的方法,则执行子类中覆盖的方法
package com.baidu.whj.animal; /** * @author Wanghj * @version 1.0 * @date 2022/12/6 21:45 */ public class Animal { private String name; private int age; public Animal() { } public Animal(String name, int age) { this.name = name; this.age = 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 void eat(){ System.out.println("Animal eat"); } } class Dog extends Animal{ public void eat(){ System.out.println("狗吃屎!"); } } class TestDog{ public static void main(String[] args) { Animal a = new Dog(); a.eat(); } }
2、类型的转换
子类对象赋值给父类引用
Animal a=new Dog();
父类引用赋值给子类引用
Animal a=new Dog(); //向下强制类型转换 Dog d=(Dog)a;
作用:当需要调用子类中的方法时,向下转型后通过子类引用对象
package com.baidu.whj.animal; /** * @author Wanghj * @version 1.0 * @date 2022/12/6 21:45 */ public class Animal { private String name; private int age; public Animal() { } public Animal(String name, int age) { this.name = name; this.age = 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 void eat(){ System.out.println("Animal eat"); } } class Dog extends Animal{ public void eat(){ System.out.println("狗吃屎!"); } public void swim(){ System.out.println("狗可以游泳!"); } } class TestDog{ public static void main(String[] args) { Animal a = new Dog(); a.eat(); //强制类型转换 Dog dog=(Dog) a; //向下类型转换之后,才能调用子类中的方法 dog.swim(); } }