从JVM看Java语言特性(三) 多态

1. 多态

多态这种特性简而言之就是用父类型别的引用指向其子类的实例,然后通过父类的方法调用实际子类的成员函数. 先抛结论: 个人理解的所谓多态, 本质上就是重写机制加上向上转型, 重写就是说子类的同名同参数的方法可以覆盖父类的方法, 子类的向上转型消除了多余方法, 就成了多态.

先给出一个多态非常简单的例子:

Father father = new Child();

这里例子中我们new一个Child实例将它丢给father这个接口, 当调用没有被重写的方法时, JVM执行父类方法, 当调用被Child重写过的方法时, 则执行子类方法.

2. 多态的实现

首先先明确一件事, 多态=重写+向上转型, 所以下面关于的多态的原理其实就是重写的原理.

对C++了解的同学应该知道C++里面有虚函数这个东西, C++为了实现多态, 在就在实例对象里面内嵌了虚函数表vtable, 这个虚函数表, 其实就是一个存储了一堆方法指针的表, 来指定调用的函数, 实现方法分派. 如果没有virtual关键字, 那么这个函数会在vtable中保存两份, 父类的函数和子类的函数都会保存. 用父类引用调用父类函数, 子类引用调用子类函数.

Java的vtable和C++大同小异, 最大的区别在于Java的vtable是在类加载时动态构建的, 大致的逻辑是这样的:

  1. 一开始继承类的vtable中的指针完全指向父类的方法, 也就是说一开始子类的vtable就是父类的vtable
  2. JVM遍历子类的所有方法, 找到所有被public或protected关键词修饰, 并且没有被static或final修饰的方法, 判断其方法签名是否与父类一致, 如果一致说明发生了重写, 那么将子类的原本指向父类的方法指针修改为指向自己的方法.
  3. 如果找出来的方法签名不一致, 说明子类自己定义了新方法, 那么就把vtable长度增加1, 并将指针指向新方法

经过以上步骤, vtable构建完成, 这张表里面分别包含了父类方法(没重写的)和子类方法(重写的), 剩下的事情就顺理成章了, 程序在调用父类引用方法的时候, JVM会通过vtable里的指针来调用方法, 这就是多态.

3. 多态的好处

多态可以实现接口复用, 隐藏实现细节, 降低代码的复杂度. 策略模式就是个最简单的例子, 策略模式让一个接口实现多种类, 但是反映在代码里面真实使用的就是父类引用Father, 这样不仅封装了内部细节, 使代码更简洁. 还增加了可维护性, 在需要这个接口或者父类实现不同功能的时候只需要将不同的子类向上转型为Father就行了, 简洁明了.

这种简化分层其实就是解耦的思想, 解耦的最终目的就是为了使不同功能的代码放在不同地方, 所谓高内聚低耦合, 从而实现强大的可维护性, 提升效率. 具体来看, 不论是多态也好, 依赖注入也好, XML配置也好, 最终目的就是将所有配置和赋值放在一起, 而把核心代码放在另一个地方, 当需要修改时, 只需要修改配置文件或者实现不同的接口就可以实现不同功能

接口复用让模块化或者分层变得简单, 在写一个大型项目的时候, 一般来说都需要很多模块互相调用. 作为一个模块的开发者我要是不想经常让别人修改代码, 我就得保持自己写的接口不变, 来修改下面的实现类.

进一步思考, 这个时候想想什么叫做控制反转就显而易见了, 目的还是为了进一步降低耦合度. 对于一个组件来说, 开发者甚至不希望使用者自己来实现接口, 而是让使用者加个注解, 我自己来帮你实现, 优点当然是显而易见的, 组件的实现类甚至连名字都可以自由更换.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • java继承 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。 继承就是子类继...
    863cda997e42阅读 655评论 0 1
  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 7,066评论 0 62
  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-java.h...
    eddy_wiki阅读 1,188评论 0 5
  • Daniel Negreanu,1974年7月26日出生。是一名加拿大职业扑克玩家,他赢得了六个世界扑克系列(WS...
    云落霓裳阅读 944评论 0 1
  • 今天上午放学,妈妈给我买了一盆儿黄色的菊花,一朵大花,四朵小花,还有三个花骨朵。非常漂亮,非常可爱!下午放学妈妈带...
    薛阔阅读 83评论 0 0