既然多态是面向对象的三大本质特征之一(其它两个是数据抽象和继承),那么 C++为什么不将方法调用的默认方式设置为动态绑定,而要通过关键字virtual进行标记呢?Bruce Eckel在《Thinking in C++》中提到,这是由于历史原因造成的,C++是从C发展而来的,而C程序员最为关心的是性能问题,由于动态绑定比静态绑定多几条指令,性能有所下降, 如果将动态绑定设定为默认方法调用方式,那么很多C程序员可能不会接受,因此,C++就将动态绑定定位成可选的,并且作出保证:If you don't use it, you don't pay for it(Stroustrup)。 但是,Java作为一个全新的完全面向对象的语言,并不存在向下兼容的问题,同时,Java的设计者也认为多态作为面向面向对象的核心,面向对象语言应该提供内置的支持,因此,Java将动态绑定作为方法调用的默认方式。 下面,我们就详细地来了解一下Java是如何为多态提供支持的。 与C++一样,Java中也有一个存放实例方法地址的数据结构,在C++中,我们把它叫做VTable,而在java中方法表(Method Table),但是两者有很多相同之处: 1、它们的作用是相同的,同样用来辅助实现方法的动态绑定。 2、同样是类级别的数据结构,一个类的所有对象共享一个方法表。 3、都是通过偏移量在该数据结构中查找某一个方法。 4、同样保证所有派生类中继承于基类的方法在方法表中的偏移量跟该方法在基类方法表中的偏移量保持一致。

5、方法表中都只能存放多态方法(Java中的实例方法,C++中是vitual方法)。

但是归根结底,C++是一门编译型的语言,而Java更加偏向于解析型的,因此上述数据结构的生成和维护是有所不同的,表现在:

1、C++中VTable和vptr是在编译阶段由编译器自动生成的,也就是说,在C++程序载入内存以前,在.obj(.o)文件中已经有这些结构的信 息;Java中的方法表是由JVM生成的,因此,使用javac命令编译后生成的.class文件中并没有方法表的信息。只有等JVM把.class文件 载入到内存中时,才会为该.class文件动态生成一个与之关联的方法表,放置在JVM的方法区中。 2、C++中某个方法在VTable的索引号是在编译阶段已经明确知道的,并不需要在运行过程中动态获知;Java中的方法初始时都只是一个符号,并不是 一个明确的地址,只有等到该方法被第一次调用时,才会被解析成一个方法表中的偏移量,也就是说,只有在这个时候,实例方法才明确知道自己在方发表中的偏移 量了,在这之前必须经历一个解析的过程。

此外,Java中不支持多重继承,也就不会像C++那样在这个泥潭中纠缠不清了,但Java也引入了新的概念,那就是接口,Interface。使用Interface调用一个实例方法跟使用一个Class来调用的过程是不一样的:

package cn.bjca.fourreference;

public class Zoo {

public static void main(String[] args) {

Pet p1 = new Dog();

Pet p2 = new Dog();

p1.say(); // 首先解析一次,得到偏移量,调用方法

p2.say(); // 不用解析,直接使用上次的得到的偏移量,调用

Cute c1 = new Dog();

Cute c2 = new Dog();

c1.cute(); // 这里使用接口来调用实例方法,首先同样会解析一次,得到偏移量,调用相应方法

c2.cute(); // 这里虽然上次已经解析过了,但是还是得重新跟上次一样重新解析一次,得到偏移量,调用

}

}

interface Cute {

public void cute();

}

class Pet {

public void say(){

System.out.println("Pet say");

}

}

class Dog extends Pet implements Cute {

public void cute(){

System.out.println("Dog cute");

}

public void say(){

System.out.println("Dog say");

}

}

为什么会有这样的区别呢?这是因为实现同一个接口的类并不能保证都是从同一个超类继承的,而且这个超类也同样实现相同的接口。因此,该接口声明的方法并不能都保证处于方法表中的同一个位置上。如,可以定义下面的类:

class Cat implements Cute{ public void cute(){ System.out.println('Cat cute'); } } 那么,Dog跟Cat同样都实现了接口Cute,因此都能够用Cute接口进行调用,但是方法cute在Dog方法表中的位置并不能保证该方法在Cat方法表中的位置是一样的。因此,对于接口调用方法,我们只好每次都重新解析一道,获得准确的偏移量,再进行调用了。这也导致了使用接口调用方法的效率要比使 用类调用实例方法低。当然,这仅仅是相对而言,JVM在实现上会予以优化,我们不能说因为接口效率低就不使用了,相反由于在面向对象作用中接口的强大作 用,java是提倡使用接口的,这一点我们是需要注意的。 还有一点,虽然java不支持类的多重继承,但是是可以实现多个接口的,那么,在Java中会不会要像C++的多重继承那样进行必要的转换呢?这个问题, 我们只需想一下两者调用的具体过程,就能知道,Java的接口方法每次调用前都是需要解析的,在这里才会取得真正的偏移量,这跟C++中编译期间取得偏移 量是不一样,因此,在Java中是不需要进行所谓的转换的。

C 多态和java多态_C与java的多态机制与区别相关推荐

  1. java 析构函数_C++与Java的区别(一)

    一,前言 网上经常看到编程语言之争,大伙儿皈依到不同门派,各自怀抱信仰,时不时还发生点儿"冲突". 这其中,C++和Java的优劣,十多年前就常吵的火热.然而时代在进步,技术在发展 ...

  2. 与java比较_C++与Java比较

    "作为一名C++程序员,我们早已掌握了面向对象程序设计的基本概念,而且Java的语法无疑是非常熟悉的.事实上,Java本来就是从C++衍生出来的." 然而,C++和Java之间仍存 ...

  3. c 异常 java异常_C ++和Java中异常处理的比较

    如今,几乎所有面向对象的语言都具有异常处理功能.在C ++和Java中,我们也可以获得这种功能.C ++中的异常处理和Java中的异常处理之间有一些相似之处,例如在两种语言中,我们都必须使用try-c ...

  4. c 调用java包_C#调用java代码(IKVMC)

    参考资料:https://blog.csdn.net/threadroc/article/details/51406587 参考1:http://www.cnblogs.com/Jack-Blog/p ...

  5. c java交互_C和Java程序之间的交互/通信

    如果您没有找到JNI'easy',那么您需要IPC(进程间通信)机制.因此,从您的C流程中,您可以与Java流程进行通信. 你在控制台重定向方面所做的是IPC的一种形式,实质上就是IPC. 由于你发送 ...

  6. Java学习笔记二十五:Java面向对象的三大特性之多态

    Java面向对象的三大特性之多态 一:什么是多态: 多态是同一个行为具有多个不同表现形式或形态的能力. 多态就是同一个接口,使用不同的实例而执行不同操作. 多态性是对象多种表现形式的体现. 现实中,比 ...

  7. Java继承_Hachi君浅聊Java三大特性之 封装 继承 多态

    Hello,大家好~我是你们的Hachi君,一个来自某学院的资深java小白.最近利用暑假的时间,修得满腔java语言学习心得.今天小宇宙终于要爆发了,决定在知乎上来一场根本停不下来的Hachi君个人 ...

  8. JAVA之旅(八)——多态的体现,前提,好处,应用,转型,instanceof,多态中成员变量的特点,多态的案例...

    JAVA之旅(八)--多态的体现,前提,好处,应用,转型,instanceof,多态中成员变量的特点,多态的案例 一.多态 我们今天又要学习一个新的概念了,就是多态,它是面向对象的第三个特征,何谓多态 ...

  9. 到底什么是面向对象,面试中怎么回答。面向过程和面向对象的区别是什么。java跨平台特性以及java和C++的区别。面向对象的三大特性——封装、继承和多态。面向对象的高拓展性以及低耦合度怎么体现?

    Java语言具有的特点:面向对象.跨平台.多线程以及网络编程 1. 和C++的区别 1.1 Java隐蔽了C++的指针,避免指针直接操作,程序更加安全. 1.2 Java类继承只能单继承,避免了C++ ...

  10. java 多态判断非空_收藏Java 面试题全梳理

    脚本之家 你与百万开发者在一起 来源 | Java建设者(ID:javajianshe) 作者 |cxuan 如若转载请联系原公众号 Java 基础篇 Java 有哪些特点 并发性的:你可以在其中执行 ...

最新文章

  1. 带宽与码元的关系_带宽、速率(波特率、比特率)和码元宽度简述
  2. Apache Beam和BigQuery的错误处理(Java SDK)
  3. 防腐投加器需要加盐吗_果干、果脯、蜜钱、水果脆片,哪个有营养?你吃对了吗?...
  4. 国漫《大闹天宫》4K修复版上线西瓜视频、鲜时光
  5. Android Studio 下载 与 安装 详细步骤
  6. 【语音处理】基于matlab GUI音乐多次回声图谱显示【含Matlab源码 1733期】
  7. matlab画图空值显示呈无色_MATLAB函数图像显示空白
  8. 通信算法之二:信道编码译码 BCH码、RS码、卷积码、Turbo码、LDPC码
  9. 递归实现从1加到100
  10. 从今往后,我就是一名前端攻城狮
  11. js中元素样式设置的六种方法
  12. 小白如何选择采集器-爬虫
  13. FICO 发票校验时修改统驭科目
  14. 企业微信 之 创建应用并添加至侧边栏
  15. 读书笔记008:《伤寒论》- 手太阳小肠经
  16. 线程编程——经典案例
  17. 记一道智力测试题-老鼠喝毒酒
  18. 【Sqlite】sqlite安装与与使用图文详解
  19. RemoteCall全新推出网页版,不安装软件也能远程技术支持
  20. 微型计算机控制技术:模拟量输入通道 简述题 + ADC接口电路设计分析

热门文章

  1. 一文了解GaussDB 200的产品架构、数据流程、组网方案、服务部署原则、企业级增强特性......
  2. 开源数据库在平安的应用实践
  3. 农业银行数据库最佳实践和发展规划
  4. 实践GoF的23种设计模式:SOLID原则(上)
  5. 华为云PB级数据库GaussDB(for Redis)揭秘第七期:高斯Redis与强一致
  6. 一文搞懂浏览器同源策略
  7. 【华为云技术分享】处理器存储模型概述(1)
  8. 手把手教你上手Git并上传项目到GitHub官网
  9. Java 复习笔记 线程Thread
  10. anaconda成功安装fasttext后,无法导入的情况