之前一直知道多态是什么东西,平时敲代码也经常用到多态,但一直没有真正了解多态底层的运行机制到底是怎么样的,这两天才研究明白点,特地写下来,跟各位同学一起进步,同时也希望各位大神指导和指正。

  多态的概念:同一操作作用于不同对象,可以有不同的解释,有不同的执行结果,这就是多态,简单来说就是:父类的引用指向子类对象。下面先看一段代码

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多态原理的更多相关文章

  1. 深入理解JAVA多态原理

    之前一直知道多态是什么东西,平时敲代码也经常用到多态,但一直没有真正了解多态底层的运行机制到底是怎么样的,这两天才研究明白点,特地写下来,跟各位同学一起进步,同时也希望各位大神指导和指正. 多态的概念 ...

  2. 深入理解java多态没有烤山药的存在,java就不香了吗?

    目录 1. 从吃烤山药重新认识多态 2. 多态前提条件[重点] 3. 多态的体现 4. 多态动态绑定与静态绑定 5. 多态特性的虚方法(virtual) 7. 向上转型 8. 向下转型 9. 向上向下 ...

  3. 深入理解Java多态机制

    从字节码层面来看,Java中的所有方法调用,最终无外乎转换为如下几条调用指令. invokestatic: 调用静态方法. invokespecial: 调用实例构造器<init>方法,私 ...

  4. 理解Java多态

    多态又称Polymophism,poly意思为多,polymophism即多种形态的意思.一种类型引用因为指向不同的子类,表现出不同的形态,使用不同的方法. 什么是多态 多态建议我们编码时使用comm ...

  5. 深入理解JAVA虚拟机原理之Dalvik虚拟机(三)

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 本文是Android虚拟机系列文章的第三篇,专门介绍Andorid系统上曾经使用 ...

  6. 深入理解Java 注解原理

    *注解的用途 注解(Annotation)是JDK1.5引入的新特性,包含在java.lang.annotation包中,它是附加在代码中的一些元信息,将一个类的外部信息与内部成员联系起来,在编 译. ...

  7. 并发编程之美,带你深入理解java多线程原理

    1.什么是多线程? 多线程是为了使得多个线程并行的工作以完成多项任务,以提高系统的效率.线程是在同一时间需要完成多项任务的时候被实现的. 2.了解多线程 了解多线程之前我们先搞清楚几个重要的概念! 如 ...

  8. 深入理解JAVA虚拟机原理之内存分配策略(二)

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 1.对象优先在Eden分配 大多情况,对象在新生代Eden区分配.当Eden区没 ...

  9. 深入理解JAVA虚拟机原理之垃圾回收器机制(一)

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 对于程序计数器.虚拟机栈.本地方法栈这三个部分而言,其生命周期与相关线程有关,随 ...

随机推荐

  1. PHP 生成器Generators的入门理解和学习

    什么是生成器Generators 生成器允许你在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组, 那会使你的内存达到上限,或者会占据可观的处理时间.相反,你可以写一个生成器 ...

  2. Python-组合数据类型

    集合类型及操作 >集合类型定义 集合是多个元素的无序组合 -集合类型与数学中的集合概念一致 -集合元素之间无序,每个元素唯一,不存在相同元素 -集合元素不可更改,不能是可变数据类型 -集合用大括 ...

  3. 【17】AngularJS Bootstrap

    AngularJS Bootstrap AngularJS 的首选样式表是 Twitter Bootstrap, Twitter Bootstrap 是目前最受欢迎的前端框架. Bootstrap 你 ...

  4. HDU 1210

    感觉就是乱搞找规律 自己写几组数据 本来开始是想着把 n 个数字每次回到原来位置各需要多少次,然后取它们的最小公倍数就好了 但是数据写着写着发现每一个数回到原来位置次数都是一样的,那么就简单了,直接第 ...

  5. [luoguP1130] 红牌(DP)

    传送门 幼儿园DP. ——代码 #include <cstdio> #include <iostream> ; << ); int a[MAXN][MAXN], f ...

  6. HDU 4902 (牛叉的线段树)

    Nice boat Problem Description There is an old country and the king fell in love with a devil. The de ...

  7. UVa - 12450 - SpaceRecon Tournament

    先上题目: Problem G: SpaceRecon Tournament SpaceRecon, the hottest game of 2011, is a real-time strategy ...

  8. BZOJ1452 count (树状数组)

    一道比较水的二维树状数组,开100个即可,只有100种颜色还是比较EZ的. Program BZOJ1452; ; maxc=; ..maxn,..maxn,..maxc] of longint; f ...

  9. Calculate S(n)

    Problem Description Calculate S(n). S(n)=13+23 +33 +......+n3 .   Input Each line will contain one i ...

  10. [kuangbin带你飞]专题六 最小生成树 N - 畅通工程再续

    相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现.现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全 ...