`

C++/Java 实现多态的方法(Java)

阅读更多

 既然多态是面向对象的三大本质特征之一(其它两个是数据抽象和继承),那么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来调用的过程是不一样的:

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多态的区别 #### 一、概述 多态是面向对象编程语言中的一个核心特性,它允许程序员能够使用基类的指针或引用指向派生类的对象,并在运行时根据对象的实际类型来选择合适的方法进行调用。这一特性增强...

    C++/Java代码分析器

    《C++/Java代码分析器详解》 在编程领域,理解和分析代码是提升技能的关键步骤。本文将深入探讨“C++/Java代码分析器”,这是一个专为C++和Java编程爱好者设计的工具,旨在帮助他们更好地理解、分析代码,从而提升...

    蓝桥杯历年C/C++/JAVA真题

    "蓝桥杯历年C/C++/JAVA真题"是一份集合了历年来蓝桥杯大赛中C、C++和Java编程语言竞赛试题的资源。蓝桥杯大赛是中国颇具影响力的计算机编程竞赛之一,旨在促进大学生的创新能力和工程实践能力,尤其在软件和信息技术...

    学习C/C++/JAVA语言的必看经典例题

    在IT行业中,编程语言是构建软件的基础工具,而C、C++和Java是三种非常重要的编程语言,尤其对于初学者来说,掌握它们的基本概念、语法和应用是至关重要的。"学习C/C++/JAVA语言的必看经典例题"这个资源集合了这三种...

    蓝桥杯竞赛练习题的题解(C/C++/Java)

    Java方面,基础知识点包括面向对象编程概念(类、对象、继承、多态),数据类型(基本类型和引用类型),控制流程(条件语句、循环),以及集合框架(ArrayList、LinkedList、HashMap等)。Java的特点在于其内存管理...

    常见C++/java面试题

    在IT行业的面试中,C++和Java作为两种广泛使用的编程语言,经常出现在笔试和面试的题目中。这两种语言各有特点,适用于不同的应用场景。本篇文章将深入探讨C++和Java的面试知识点,帮助求职者做好充分准备。 对于...

    C++/java 继承类的多态详解及实例代码

    C++和Java都是支持多态的语言,但它们在实现多态的方式上有所不同。本文将深入探讨这两种语言中的继承类多态,并通过实例代码进行解析。 在C++中,多态性主要依赖于虚函数。在上面的示例中,`Animal` 类没有声明...

    2012年10月 搜狗C++/JAVA校园招聘笔试题

    3. **封装、继承与多态**:作为面向对象的三大特性,Java通过访问修饰符实现封装,支持单一继承和接口的多继承,以及多态性的体现。 4. **集合框架**:Java提供了丰富的集合框架,如ArrayList、LinkedList、HashMap...

    C/C++/Java/android/PHP/iOS/Python期末试卷.rar

    C++ 是 C 语言的扩展,增加了面向对象编程(OOP)的概念,如类、对象、封装、继承和多态,使得它更适合大型软件项目的开发。 知识点包括: 1. C 语言的基本语法:变量、数据类型、运算符、控制结构(如条件语句、...

    C++/Java/C#/SQL 面试题 答案

    - Java 8及以上新特性:Lambda表达式、流API、方法引用来实现函数式编程。 3. **C#**:C#是微软公司推出的一种.NET框架下的编程语言,常用于Windows应用程序开发。面试中可能涉及的C#知识点包括: - 基础语法:类...

    symbian笔试题目啊c++/java

    继承和多态是面向对象编程的特性,继承允许子类继承父类的属性和方法,多态则允许子类对象替代父类对象。重写是指子类对父类方法的再次实现,回调函数则是在特定事件发生时调用的函数,常用于异步编程和事件驱动模型...

    c/C++/Java 经典面试题目

    在IT行业中,C、C++和Java是三大基础且重要的编程语言,广泛应用于系统级编程、游戏开发、软件工程以及互联网应用等多个领域。面试时,掌握这些语言的关键知识点和技术是必不可少的。以下是一些根据标题和描述提炼出...

    C/C++,Java面试题汇总

    1. **面向对象**:封装、继承、多态的基本概念及实现方式。 2. **STL**:标准模板库,包括容器(如vector, list, map)、迭代器、算法等。 3. **模板**:函数模板、类模板的使用和理解。 4. **异常处理**:try-catch...

    程序面试试题汇总——C/C++/Java/软件测试

    在程序面试过程中,掌握C,C++,Java以及软件测试的知识是至关重要的。这份资源集合了这四个领域的面试和笔试题目,旨在帮助求职者更好地准备技术面试,提升自身的竞争力。 一、C语言与C++面试题汇总 1. C语言基础...

    0854考研复试 综合面试速成(1):C/C++/Java常识 Akira37.pdf

    ### 0854考研复试综合面试速成(1):C/C++/Java常识 #### C语言与C++语言的基础对比 - **C语言**: - 面向过程,强调算法和数据结构。 - 程序设计侧重于如何通过一系列步骤处理输入并产生输出。 - 不具备类、...

    达内面试笔记,分享(C++/Java)

    - **继承与多态**:继承的基本概念、基类与派生类、虚函数与抽象类、多态的实现方式。 - **模板**:模板的基本概念、函数模板与类模板的定义与使用。 - **异常处理**:try-catch-finally机制、抛出异常与捕获异常的...

    java 多态.docx

    另外,Java中的方法默认都是虚拟的(相当于C++中的虚函数),这意味着即使方法没有被声明为`abstract`或`final`,在子类中也可以被重写,并在运行时根据对象的实际类型确定调用哪个版本的方法。如果一个方法被声明为...

    2018年蓝桥杯C/C++ B组与 JAVA B组 真题

    【标题】2018年蓝桥杯C/C++ B组与 JAVA B组 真题解析 在编程竞赛领域,蓝桥杯是一项备受瞩目的赛事,尤其对于学习C/C++和Java的程序员来说,其真题具有极高的参考价值。2018年的蓝桥杯B组比赛,不仅考验了参赛者的...

    CPlus_to_Java_Converter;C++转java工具

    3. **模板与泛型**:C++的模板提供了静态多态,而Java通过泛型实现了类似功能。转换器需要将模板转换为Java的泛型,但要注意Java泛型的边界和限制。 4. **异常处理**:C++的异常处理与Java的有所不同。转换器需要将...

Global site tag (gtag.js) - Google Analytics