深入理解JAVA多态原理
之前一直知道多态是什么东西,平时敲代码也经常用到多态,但一直没有真正了解多态底层的运行机制到底是怎么样的,这两天才研究明白点,特地写下来,跟各位同学一起进步,同时也希望各位大神指导和指正。
多态的概念:同一操作作用于不同对象,可以有不同的解释,有不同的执行结果,这就是多态,简单来说就是:父类的引用指向子类对象。下面先看一段代码
package polymorphism; class Dance {
public void play(){
System.out.println("Dance.play");
}
public void play(int i){
System.out.println("Dance.play" + i);
}
} class Latin extends Dance {
public void play(){
System.out.println("Latin.play");
}
public void play(char c){
System.out.println("Latin.play" + c);
}
}
class Jazz extends Dance {
public void play(){
System.out.println("Jazz.play");
}
public void play(double d){
System.out.println("Jazz.play" + d);
}
}
public class Test {
public void perform(Dance dance){
dance.play();
}
public static void main(String[] args){
new Test().perform(new Latin()); // Upcasting
}
}
执行结果:Latin.play。这个时候你可能会发现perform()方法里面并没有类似“if 参数类型 = Dance/Latin”这样的判断,其实这就是多态的特性,它消除了类型之间的耦合关系,令我们可以把一个对象不当做它所属的特定类型来对待,而是当做其基类的类型来对待。因为上面的Test代码完全可以这么写:
public class Test {
public void perform(Latin dance){
dance.play();
}
public void perform(Jazz dance){
dance.play();
}
public static void main(String[] args){
new Test().perform(new Latin()); // Upcasting
}
}
但是这样你会发现,如果增加更多新的类似perform()或者自Dance导出的新类,就会增加大量的工作,而通过比较就会知道第一处代码会占优势,这正是多态的优点所在,它改善了代码的组织结构和可读性,同时保证了可扩展性。
那么到底JVM是怎么指向Latin类中play()的呢?为了解决这个问题,JAVA使用了后期绑定的概念。当向对象发送消息时,在编译阶段,编译器只保证被调用方法的存在,并对调用参数和返回类型进行检查,但是并不知道将被执行的确切代码,被调用的代码直到运行时才能确定。拿上面代码为例,JAVA在执行后期绑定时,JVM会从方法区中的Latin方法表中取到Latin对象的直接地址,这就是真正执行结果为什么是Latin.play的原因,在解释方法表之前,我们先了解一下绑定的概念。
将一个方法调用同一个方法主体关联起来被称作绑定,JAVA中分为前期绑定和后期绑定(动态绑定或运行时绑定),在程序执行之前进行绑定(由编译器和连接程序实现)叫做前期绑定,因为在编译阶段被调用方法的直接地址就已经存储在方法所属类的常量池中了,程序执行时直接调用,具体解释请看最后参考资料地址。后期绑定含义就是在程序运行时根据对象的类型进行绑定,想实现后期绑定,就必须具有某种机制,以便在运行时能判断对象的类型,从而找到对应的方法,简言之就是必须在对象中安置某种“类型信”,JAVA中除了static方法、final方法(private方法属于)之外,其他的方法都是后期绑定。后期绑定会涉及到JVM管理下的一个重要的数据结构——方法表,方法表以数组的形式记录当前类及其所有父类的可见方法字节码在内存中的直接地址。
动态绑定具体的调用过程为:
1.首先会找到被调用方法所属类的全限定名
2.在此类的方法表中寻找被调用方法,如果找到,会将方法表中此方法的索引项记录到常量池中(这个过程叫常量池解析),如果没有,编译失败。
3.根据具体实例化的对象找到方法区中此对象的方法表,再找到方法表中的被调用方法,最后通过直接地址找到字节码所在的内存空间。
最后说明,域和静态方法都是不具有多态性的,任何的域访问操作都将由编译器解析,因此不是多态的。静态方法是跟类,而并非单个对象相关联的。对动态绑定还有不明白的请看资料链接,个人感觉分析的很到位
参考资料:http://hxraid.iteye.com/blog/428891
深入理解JAVA多态原理的更多相关文章
- 【转】深入理解Java多态原理
之前一直知道多态是什么东西,平时敲代码也经常用到多态,但一直没有真正了解多态底层的运行机制到底是怎么样的,这两天才研究明白点,特地写下来,跟各位同学一起进步,同时也希望各位大神指导和指正. 多态的概念 ...
- 深入理解java多态没有烤山药的存在,java就不香了吗?
目录 1. 从吃烤山药重新认识多态 2. 多态前提条件[重点] 3. 多态的体现 4. 多态动态绑定与静态绑定 5. 多态特性的虚方法(virtual) 7. 向上转型 8. 向下转型 9. 向上向下 ...
- 深入理解Java多态机制
从字节码层面来看,Java中的所有方法调用,最终无外乎转换为如下几条调用指令. invokestatic: 调用静态方法. invokespecial: 调用实例构造器<init>方法,私 ...
- 理解Java多态
多态又称Polymophism,poly意思为多,polymophism即多种形态的意思.一种类型引用因为指向不同的子类,表现出不同的形态,使用不同的方法. 什么是多态 多态建议我们编码时使用comm ...
- 深入理解JAVA虚拟机原理之Dalvik虚拟机(三)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 本文是Android虚拟机系列文章的第三篇,专门介绍Andorid系统上曾经使用 ...
- 深入理解Java 注解原理
*注解的用途 注解(Annotation)是JDK1.5引入的新特性,包含在java.lang.annotation包中,它是附加在代码中的一些元信息,将一个类的外部信息与内部成员联系起来,在编 译. ...
- 并发编程之美,带你深入理解java多线程原理
1.什么是多线程? 多线程是为了使得多个线程并行的工作以完成多项任务,以提高系统的效率.线程是在同一时间需要完成多项任务的时候被实现的. 2.了解多线程 了解多线程之前我们先搞清楚几个重要的概念! 如 ...
- 深入理解JAVA虚拟机原理之内存分配策略(二)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 1.对象优先在Eden分配 大多情况,对象在新生代Eden区分配.当Eden区没 ...
- 深入理解JAVA虚拟机原理之垃圾回收器机制(一)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 对于程序计数器.虚拟机栈.本地方法栈这三个部分而言,其生命周期与相关线程有关,随 ...
随机推荐
- JavaScript---网络编程(11)--DHTML技术演示(4)-单选框/下拉菜单/添加文件
本节讲述单选框/下拉菜单/添加文件,综合css,html和JavaScript. 单选框: 实现的功能是:(类似平时的性格测试) 先隐藏一部分页面,然后通过点击单选框来显示. 再通过选项的选择-(每个 ...
- 数据库分页--MySQL数据库
关于实现MySQL分页的最简单的方法就是利用mysql数据库的limit函数:limit [offset,] rows SELECT * FROM 表名称 LIMIT M,N limit 子句可以被用 ...
- js修改编辑器内容、修改iframe子页内容
$('#question-stem-uploader').on('click','',function(){ //获取编辑器内容(ke-edit-iframe: 编辑器iframe的classm名称) ...
- Linux中的文件压缩,打包和备份命令
压缩解压命令 gzip 文件 -c : 将压缩数据输出到屏幕,可用来重定向 -v 显示压缩比等信息 -d 解压参数 -t 用来检验一个压缩文件的一致性看看档案有没错 -数字 : 压 ...
- 一个分门别列介绍JavaScript各种常用工具的脑图
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:一个分门别列介绍JavaScript各种常用工具的脑图.
- linux 入侵检查转载
转载 本文给大家收集整理了一些审查Linux系统是否被入侵的方法,这些方法可以添加到你运维例行巡检中. 1. 检查帐户 代码如下: # less /etc/passwd # grep :0: /etc ...
- ctrl+z的JAVA实现,借助了命令模式(command pattern)
前些天学习<<JAVA与模式>>,到命令模式时,随带给了一个CTRL+Z案例的实现,想来学习编程这么久,CTRL+Z还没有认真实现过. 因此,借助JAVA与模式里面的源代码,自 ...
- [TypeScript] Installing TypeScript and Running the TypeScript Compiler (tsc)
This lesson shows you how to install TypeScript and run the TypeScript compiler against a .ts file f ...
- servlet和手动创建servlet,断点调试
1. 什么是Servlet Servlet是一种用Java语言编写的Web应用组件 Servlet主要用于动态网页输出,扩展了Web服务器的功能 Servlet由Servlet容器进行管理 2. ...
- 【转】iOS应用崩溃日志揭秘2
这篇文章还可以在这里找到 英语 场景 4: 吃棒棒糖时闪退! 用户邮件说, "当rage master吃棒棒糖时应用就闪退-" 另一用户说, "我让rage master ...