深入理解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 对于程序计数器.虚拟机栈.本地方法栈这三个部分而言,其生命周期与相关线程有关,随 ...
随机推荐
- pyhton 查找一个数的所有因子 以及 判断一个数是否是质数 两个小脚本
最近看到一个网站, 欧拉计划.挺好玩,都是一些算法题.这是本站:http://projecteuler.net/problems 这个是中文站:http://pe.spiritzhang.com/ 下 ...
- Tomcat7.0配置
Tomcat7.0下载地址:http://tomcat.apache.org/download-70.cgi 选择符合自己操作系统的版本即可(本机win8-64位系统),选择如下: http://11 ...
- ARM学习日记
2012-05-15 1.ARM开发板环境的搭建,nor启动,通过suppervivi,下载vivi---下载Kernel----下载文件系统,然后Nandflash启动即可. 2.在/etc/ini ...
- nyoj 1036 非洲小孩【贪心区间选点】
非洲小孩 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 家住非洲的小孩,都很黑.为什么呢?第一,他们地处热带,太阳辐射严重.第二,他们不经常洗澡.(常年缺水,怎么洗 ...
- 解决Ubuntu Server 12.04换了网卡MAC地址后 网络不可用的问题.
重装了系统,新建了一个ubuntu虚拟机,加载原来的镜像,结果启动后网络变得不正常了,提示信息 Waiting for network configuration...Waiting up to 60 ...
- jquery ajax 使用layer的超时提示
<!DOCTYPE html> <html> <head> <title>我是标题</title> <meta name=" ...
- 【JAVA - SSM】之MyBatis开发DAO
在SSM框架中的DAO层就是MyBatis中的Mapper,Mapper分为两部分:Mapper接口(JAVA文件)和Mapper映射文件(XML文件).DAO开发(Mapper开发)有两种方式:原始 ...
- JSP http头消息
头 描述 Accept 指定MIME类型 Accept-Charset 编码,例如utf-8 Accept-Encoding 编码方式,例如使用gzip压缩 Accept-Language 语言,例如 ...
- hibernate.hbm.xml配置文件内容说明
下面是一个自动生成的配置文件: <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PU ...
- Lua的安装
Lua 是一个扩展式程序设计语言,它被设计成支持通用的过程式编程,并有相关数据描述的设施. Lua 也能对面向对象编程,函数式编程,数据驱动式编程提供很好的支持.它可以作为一个强大.轻量的脚本语言 ...