做梦都要背出来的三个必要条件
代码实例
package cn.haien.polymorphism;
public class Animal {
public void voice() {
System.out.println("普通动物的叫声");
}
}
class Cat extends Animal{
public void voice() {
System.out.println("喵喵喵");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal{
public void voice() {
System.out.println("汪汪汪");
}
}
package cn.haien.polymorphism;
public class Test {
public static voidtestAnimalVoice(Animal c) {//形参使用多态
//编译时,扫描到Animal
//并发现其中有voice这个方法就通过了
c.voice();
if(c instanceof Cat)//instanceof 表示判断前者是不是后面类的实例化对象
((Cat)c).catchMouse();//如果是的话,强制转换为Cat类型并调用它自己的方法
}
public static void main(String[] args) {
Animal a = new Cat();
Animal b = new Dog();
testAnimalVoice(a);
testAnimalVoice(b);
Cat a2 = (Cat)a;//只能把引用该子类的父类对象强制转换为相应子类,其他都不行
//Cat b2 = (Cat)b;
a2.catchMouse();
//b2.catchMouse();//编译通过,但运行出错,编译通过是因为编译器比较傻,你让它强制转换为什么它就强制转换为什么
//但是真正运行的时候实际是什么就是什么,不能把一只狗强制转换为一只猫
}
}
其实返回值也可以使用多态
内存分析
- 编译文件,从上到下、从左到右开始扫描,首先将Test加载到方法区即帧中(在Test文件中点运行)
- 扫描到main方法则开始运行
- 遇到类名则将其加载到帧中
遇到new则创建对象并在栈中分配内存,那么要先调用类的构造器。
PS:构造器中实际隐式地传入this和supper,,而supper指向上级父类,一直找到Object类后开始一级一级往下执行构造器,每一级的this都指向最终要创建的对象而不会不同,只有supper是不同的
- 遇到testAnimalVoice方法开始传参,开辟栈帧存放形参c,同样指向堆中的类构造
内存深入分析
package cn.haien.polymorphism2;
public class HttpServlet {
public void service() {
System.out.println("HttpServlet.service()");
doGet();//实际上是this.doGet();
}
public void doGet() {
System.out.println("HttpServlet.doGet()");
}
}
class myServlet extends HttpServlet{
public void doGet() {
System.out.println("myServlet.doGet()");
}
}
package cn.haien.polymorphism2;
public class TestHttpServlet {
public static void main(String[] args) {
HttpServlet a = new myServlet();
a.service();//内含doGet的调用,实际上调用的是子类myServlet的doGet函数
}
}