面向对象中多态的理解(JAVA)

2 篇文章 0 订阅

首先我们必须弄清楚什么是多态

首先多态是在封装的基础上才有的(因为对象由封装而成)

其次多态指的是:同类型对象,表现得不同的形态。

它的表现形式Father f=new Son();

多态还有三个前提

1.有继承关系

2.有父类引用指向子类对象:即子类对象赋值给子类类型

比如Person是Student 和Teacher的父类

我们创建了一个方法 public void register(Person p) 这里的形参可以用Student或者Teacher类型的象传入

3.有方法重写(子类中成员方法对父类的方法的重写,即覆盖虚方法表中的方法)

接下来我们看一下多态调用成员的例子

首先创建父类(Animal)和子类(Dog),具体如下图:

接下来看main方法中如何调用:

我们看到了父类类型(Animal)的对象调用了子类(Dog)的构造方法(new Dog()),这一个经典的多态形式

接下来我们直接输出a.name,得到的结果是"动物",是我创建在父类中的变量初始值,而不是子类中的"狗"

接下来我们从内存角度分析下整个运行过程:

①如图,首先加载main方法的字节码文件

②看到main()中第一行出现Animal类,继续加载Animal.class这一字节码文件,同时加载Animal类中的成员变量和成员方法,加上要传给子类的虚方法表(其中就有show()这一方法)

③又看到new Dog(),继续加载Dog.class这一字节码文件,然后加载其中的成员变量和成员方法,加载完方法后发现,我们的Dog类中的show()方法对父类的show()做了重写操作,更新自己的虚方法表,使其中的show()方法是自己重写的内容

④因为是用Dog()这一构造方法new了一个Animal类型的对象 a(内存中地址是001),所以要在堆内存中创建 Animal对象,其中存有两个成员变量的值(父类和子类的name值),左边是父类的name="动物",右边是子类中的name="狗"。

⑤我们看到了sout(a.name)让我们打印a.name的值,因为a是Animal类型的对象

编译的时候是先判断a所属的Animal类中有没有叫name的成员变量,有则编译通过,没有则编译失败

运行的时候是直接看左边父类Animal(因为a就是Animal类型)中的name的值,直接打印父类的name值:"动物"

(变量调用:编译看左边,运行也看左边)

补充:如果是Dog d=new Dog()创建的话,d.name就是先看右边子类中有没有,没有再看左边父类中有没有name值

⑥这时候我们看到代码进行到了a.show()。

从编译的角度,JVM会去找a所在Animal类中有没有叫show()的方法,有则编译通过,没有则编译失败。

运行时:实际上是相当于查看最新的虚方法表,刚刚第三步加载Dog.class的时候,我们就已经通过Dog类中重写的show()更新了虚方法表中的show(),所以我们运行时调用的就是Dog类中的show()

(方法调用:编译看左边,运行看右边)

最后的运行结果:

总结:

在使用面向对象中多态调用的时候,要区分调用成员变量和成员方法,

他们的编译判定都是看对象类中存不存在这样的变量和方法,有则编译,无则报错

运行的时候:输出的变量是输出对象数据类型那个类当中的成员变量

输出的方法是看(重写后)最新的虚方法表中的方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值