(转载)图解Java多态内存分配以及多态中成员方法的特点
图解Java多态内存分配以及多态中成员方法的特点
worker.startWork(); 为什么编译不通过呢?提示:找不到符号。
因为引用变量worker是Person类型,在Person类的方法表中查找方法startWork(),找得到吗?找不到,更别提常量池解析了。编译失败。
【子类有,父类有,重写,非静态】调用子类!!!
worker.say(); 子类重写父类方法,被重写的方法在子类跟父类的方法表中索引相同。
调用的时候,在父类类型的方法表中查找say方法的索引,然后把索引存到PolDemo类的常量表中(常量池解析,就是用Person类方法表中的索引项来代替常量池中的符号引用)。
因为索引相同,直接拿常量表中say方法的索引去子类方法表中调用say()方法。 所以,此时调用的是被子类重写的方法。见图中的内存分配。
【子类有,父类有,静态】调用当前引用类型变量类型中的方法。
因为静态是属于类的,由实例共享,所以只看当前引用变量所属的类中的静态方法。
多态中(父类引用指向子类对象)成员方法(非静态)有以下特点:
编译期根据引用类型变量所属的类型方法表中是否有调用的方法,没有编译失败。
运行期根据在堆中创建对象的实际类型找到对应的方法表,从中确定具体的方法在内存中的位置。
堆中实例对象:子类包含父类,子类对父类说:你的就是我的,我的还是我的。
多态中成员变量的特点分析:
无论编译期还是运行期,都只参考引用类型变量所属的类中是否有对象的成员变量。
小的总结:
再来看这条语句:Person worker = new Worker(): 多态,父类引用指向子类对象。
跟这句代码的作用是一样的,Worker w = new Worker(); Person worker = w; 就是子类的引用传给父类类型的引用。向上转型,都指向一个实例对象(子类)。
1:为什么可以将子类实例对象的引用传给父类类型引用呢?
答:多态的体现,鸽子是鸟类,鹦鹉是鸟类,喜鹊是鸟类,它们都是鸟类,这就是鸟类的多种表现形态(多态),
它们有鸟类的基本特征与行为,并且还有自己特有的行为,那就会把鸟类的基本特征与行为继承过来给自己。extends关键字声明了他们的关系。
程序中这句话 鸟类 xx鸟 = new 鸽子();就创建了一个鸟类的引用,它是鸽子。
类的概念是抽象的,所以它就仅仅是个引用,只有引用到实例对象,它才真正实现了自己。
2:父与子的关系会怎样呢?
由于Worker类继承自Person类,所以会先加载Person类并初始化成员变量在Worker类实例对象中。这就是子类继承过来的成员变量。
如果子类中定义了与父类相同的成员变量,变量不会存在重写,子类实例对象中会有两份相同名称的实例变量,调用时,父类的会被隐藏。
如果想调用父类被隐藏的成员变量,那就要使用super关键字。
同样,子类会继承父类的成员方法作为自己的成员方法,如果子类定义了与父类相同的成员方法(重写),多态中会调用子类自己的成员方法。
3:多态,又有什么好处呢?跟这样写(Worker worker = new Worker();)有什么区别,不一样继承父类的属性方法吗?
首先明确: Worker worker = new Worker();这样写仅仅是继承关系。不存在多态特性。
Person worker = new Worker(); 这样写就展示了多态的关系,鸽子是鸟类的一种表现形态。
有啥好处?一句话概括:提高了程序的扩展性,表现在什么地方呢?比如:
现在有个工厂,能解析鸟类的语言,鸽子是鸟类吧?Ok,那建一个工厂,让鸽子说。
public static void doWork(Dove dove) {
String sound = dove.say(); // ... 拿到鸽子说的话
}
鹦鹉是鸟类吧?Ok,那建一个工厂,让鹦鹉说。
public static void doWork(Parrot parrot) {
String sound = parrot.say(); // ... 拿到鹦鹉说的话
}
如果还有一千个鸟类要说话,那我岂不得建一千座工厂?。。。累不累?那既然都是鸟类,我建一个鸟类的工厂不就行了嘛?
public static void doWork(Bird bird) {
String sound = bird.say(); // ... 拿到xx鸟说的话。。。
}
这时候,无论你什么鸟进来,我都让你说话,而且说得都是你自己的话,因为你继承我并重写了你的功能。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Worker w = (Worker)worker; // 向下转型。目的,为了调用子类非继承父类、自己特有的方法。
因为多态有个弊端,只能使用父类的引用访问父类的成员。所以向下转型是为了访问子类自己的成员。
首先,worker引用指向的实例对象本来就是子类类型的。所以赋值给子类类型引用变量非常可以。
然后现在用子类类型的引用就可以访问自己的成员方法了啦啦啦。
(转载)图解Java多态内存分配以及多态中成员方法的特点的更多相关文章
- 图解Java继承内存分配
图解Java继承内存分配 继承的基本概念: (1)Java不支持多继承,也就是说子类至多只能有一个父类. (2)子类继承了其父类中不是私有的成员变量和成员方法,作为自己的成员变量和方法. (3)子 ...
- Java 对象内存分配与回收
JVM内存区域模型: * 程序计数器,内存区域极小,是当前线程的字节码执行行号指示器: * 虚拟机栈.本地方法栈,即平时所说的“栈”,是虚拟机用来执行方法(包括Java.非Java方法)时,使用的临时 ...
- java继承内存分配
java继承内存分配 继承的基本概念: * Java不支持多继承,也就是说子类至多只能有一个父类. * 子类继承了其父类中不是私有的成员变量和成员方法,作为自己的成员变量和方法. * 子类中定义的成员 ...
- JAVA虚拟机内存分配与回收机制
Java虚拟机(Java Virtual Machine) 简称JVM Java虚拟机是一个想象中的机器,在实际的计算机上通过软件模拟来实现.Java虚拟机有自己想象中的硬件,如处理器.堆栈.寄存器等 ...
- java 继承内存分配
今天,复习的是继承的内存分配.我们知道,Java中内存可以初略分为堆.栈.方法区. package sort; class Person{ public int age; public String ...
- 深入理解java虚拟机---内存分配策略(十三)
转载请注明原文地址:https://blog.csdn.net/initphp/article/details/30487407 Java内存分配策略 使用的ParNew+Serial Old收集器组 ...
- Java的内存分配
java内存分配 A:栈 存储局部变量 B:堆 存储所有new出来的 C:方法区(方法区的内存中) 类加载时 方法信息保存在一块称为方法区的内存中, 并不随你创建对象而随对象保存于堆中; D:本地方法 ...
- 小白请教几个关于Java虚拟机内存分配策略的问题
最近在看周志明所著的<深入理解Java虚拟机>,有几个问题不太明白,希望对虚拟机有研究的哥们儿帮我解答一下.先说一下我进行试验的环境: 操作系统:Mac OS X 10.11.6 EI C ...
- 理解java虚拟机内存分配堆,栈和方法区
栈:存放局部变量 堆:存放new出来的对象 方法区:存放类的信息,static变量,常量池(字符串常量) 在堆中,可以说是堆的一部分 创建了一个student类,定义了name属性, id静态变量 ...
随机推荐
- js+php大文件分片上传
1 背景 用户本地有一份txt或者csv文件,无论是从业务数据库导出.还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工.挖掘和共创应用的时候,首先要将本地文件上传至ODPS,普通的小文件通 ...
- Ubuntu 16.04下使用docker部署rabbitmq
(以下docker相关的命令,需要在root用户环境下或通过sudo提升权限来进行操作.) 1.拉取rabbimq镜像到本地 docker pull rabbitmq 2. Docker运行rabbi ...
- 特征提取算法(1)——纹理特征提取算法LBP
模式识别中进行匹配识别或者分类器分类识别时,判断的依据就是图像特征.用提取的特征表示整幅图像内容,根据特征匹配或者分类图像目标. 常见的特征提取算法主要分为以下3类: 基于颜色特征:如颜色直方图.颜色 ...
- 设计模式学习笔记——Composite 组合模式
用于描述无限层级的复杂对象,类似于描述资源管理器,抽象出每一个层级的共同特点(文件夹和文件,展开事件) 以前描述一个对象,是将整个对象的全部数据都描述清楚,而组合模式通过在对象中定义自己,描述自己的下 ...
- NSDate 那点事
转载自:http://my.oschina.net/yongbin45/blog/150114 NSDate对象用来表示一个具体的时间点. NSDate是一个类簇,我们所使用的NSDate对象,都是N ...
- SpringMVC常用方法总结
*) @RequestMapping(value="/xxx/{id}",method={RequestMethod.GET}) method 不写的话,默认GET.POST都支持 ...
- 你还没搞懂this?
一.前言 this关键字是JavaScript中最复杂的机制之一.它是一个很特别的关键字,被自动定义在所有函数的作用域中.对于那些没有投入时间学习this机制的JavaScript开发者来说,this ...
- jni中arm64-v8a,armeabi-v7a,armeabi文件夹的意义和用法<转>
jni中arm64-v8a,armeabi-v7a,armeabi文件夹的意义和用法 起因 之前并没有关注这块,直到:您的应用被拒绝,原因:xplay5sQ心里点击笑值点击拍照显示停止运行,查看发过来 ...
- 最近使用的两个工具 winscp和xshell
最近在编译MONO源码时用到了这两个工具,感觉挺好,记录备忘 WINSCP 长这样 用于可视化的查看和操作远程服务器上的文件 xshell用于命令行下操作远程服务器,服务器的同学好多在用这个.命令行是 ...
- MySQL高可用方案 MHA之二 master_ip_failover
异步主从复制架构master:10.150.20.90 ed3jrdba90slave:10.15.20.97 ed3jrdba9710.150.20.132 ed3jrdba132manager:1 ...