多态的向上转型
多态的前提:两个对象(类)存在继承关系
多态向上转型的本质:父类的引用指向了子类的对象
话不多说,上代码:
class Animal { //父类
public int age = 10;
public void eat() {
System.out.println("动物吃食物");
}
public void sleep() {
System.out.println("动物睡觉");
}
}
class Cat extends Animal{ //子类
public int age = 3;
public void eat() {
System.out.println("猫吃鱼");
}
public void catchfish() {
System.out.println("猫抓鱼");
}
}
一、输出会是什么?
public static void main(String[] args) {
Animal animal = new Cat();
System.out.println("=======向上转型=======");
animal.eat();
animal.sleep();
animal.catchfish();
System.out.println(animal.age);
Cat cat = (Cat) animal;
System.out.println("=======向下转型=======");
cat.eat();
cat.catchfish();
cat.sleep();
System.out.println(cat.age);
}
二、内存分析
new Cat() 在堆中创建了一个 Cat 对象,其中包含父类 Animal 的属性和方法(黄色部分)以及子类 Cat 的属性和方法(灰色部分)。
用父类的引用 animal 指向该对象。此时发生了向上转型,引用 animal 实际上指向的是堆中属于父类 Animal 的那一部分(即黄色的那一部分),所以:
- 此时 animal.age = 10。
- 但由于 eat() 被重写了,所以会执行 Cat 类中的 eat() 方法,输出“猫吃鱼”。黄色部分中的 eat 用红色标注表示被重写/覆盖。
- animal.catchfish() 会报错,因为访问不到catchfish() 方法。
再使用 Cat cat = (Cat) animal; 进行向下转型,就恢复到了正常的继承情况:
- 此时 animal.age = 3。
- eat() 被重写,输出“猫吃鱼”。
- 可正常访问 catchfish() 方法。也可正常访问继承来的 sleep() 方法。
三、输出结果
Animal animal = new Cat(); //向上转型
System.out.println("=======向上转型=======");
animal.eat(); //猫吃鱼
animal.sleep(); //动物睡觉
//animal.catchfish(); 无法访问
System.out.println(animal.age); //10
Cat cat = (Cat) animal; //向下转型
System.out.println("=======向下转型=======");
cat.eat(); //猫吃鱼
cat.catchfish(); //猫抓鱼
cat.sleep(); //动物睡觉
System.out.println(cat.age); //3
四、说明
对 JVM 的描述如若有误,欢迎指正。
参考:
1.韩顺平 零基础30天学会Java
2.https://blog.csdn.net/huyuyang6688/article/details/42566043