JAVA多态性;我和网友交流实录

JAVA多态性<==>;我和网友交流实录    zosatapo(原作)
  
关键字     Java 多态性 面向对象
  


我在这里公开和我dennisboys的学习交流信件,我们主要在谈java中多态性问题。
这里感谢我的好朋友能给我一个结合自己能力解释问题的机会,在解释中有出错
或者需要讨论的部分希望能通知我一声。



上篇关于多态性的文章请参阅我前面写的<<java多态性实例解释一文>;>;.




*******************************************************************************
    网友dennisboys的提问部分开始
*******************************************************************************
从头到尾把你的代码看了n次,画了n个图(关于父类和子类的函数地址图),有以下一些迷惑
test t=new test()&#59;
base b=new base()&#59;
b=t&#59;



/*
问题一:
这里是把父类的引用指向子类,那是不是说调用父类的方法就等于调用子类的方法呢?就是
如果b.display2()不是调用子类的display2()方法吗?而子类有display2()方法,为什么不能
调用呢?(我试过写代码了,果然如你所说是出错的。)



对于以上的问题,你有一段文字好像是对其作解译的。不过我不太清楚。不知是不是以下这
段。



引用原文:
同时可能有人要问,子类中那个函数地址不是也在虚拟函数表中吗?
很高兴你问这样的问题,但是父类引用看到的虚拟函数表是没有
那个函数项目的,因为他对于父类引用绝对是不可见。



我现在理解是如果在子类中如对方法作了更改或新增的方法,对父类来说是不可见的?理解
对吗??
*/



问题二:
((test)b).display()&#59;
另一个迷感就是你说的强制转换类型的语法到底是怎样的??我不明白为((test)b)代表什么




不过说回来(我怎么觉得这个例子是在说继承??),这个例子使我对继承有了很深的认识
,我倒是觉得对多态性还是一知半解,(别说我笨笨)可能我还没清楚到底哪用到了多态性,
不过请先回复了我以上两个问题,希望你回复了我以上两个问题(结合我研究你的代码)使我
对多态性有更好更深的认识。。
*******************************************************************************
    网友dennisboys的提问部分结束
*******************************************************************************




*******************************************************************************
    zosatapo的解释部分开始
*******************************************************************************



你真的应该谢谢我的,因为我辛辛苦苦打了篇文章,
因为网络原因没有能成功保存,害了我重写一次,
没有办法,谁叫你是我的好朋友呢。



首先谢谢你耐心看完我的文章。



下面我就我上次写的那篇文章和你的问题作简单的说明但是又比较复杂的说明。



我上次写的那篇文章存在一处写作错误,我在网上已经修正了,这里告诉你一下:



上次的原文中有这样的几句话
****************************************
  // 下面调用会出错的
  file://t.display2()&#59;
  file://应该象下面那样
  ((test)b).display2()&#59;
******************************************



这几句话写作上有错误:
应该改成成下面这样:



**********************************************
  // 下面调用[不]会出错的  (这里多了一个[不]字)
  file://t.display2()&#59;
#########################################  
  实际上我上面这两行跟本文没有关系的
  但是为了你很好的理解动态性,你可以
  把上面的代码与下面的进行比较。
#########################################
  file://下面这行调用不会出错
  file://b.display2()&#59;  这里加了一行
  file://应该象下面那样
  ((test)b).display2()&#59;
**********************************************‘




下面正式开始我们今天的话题,正对你的问题我进行解释,
这里我尽可能的解释详细一点让你明白,实际上这里太复杂
涉及到OOP的具体实现问题,这个问题又不得不涉及到编译器
问题,主要的又是对象内存布局问题。



由于第二个问题比较简单,我把回答问题的次序颠倒一下。



*********
  问题二
*********
你说的很对,我这里解的是继承,但是我这里解的不仅仅是继承的
问题。可以这样是你说的继承只是我解释动态性问题的一个途径和
手段而已,因为继承和多态性一样是面向对象中很重要的概念,不
是写一点文章就可以说明白的。



简单一点和不精确的说,动态性与是继承不可分割的,如果没有继承
根本就谈不上多态性的。所以我说你说的对,但是你没有真正明白我
例子的作用(55555555~~~~~~~~~~~~~我的心血呀)



*********
  问题一
*********
首先需要说明的是你对这个问题的理解是不正确的。



这个问题更是复杂的一塌糊涂,我尽量用一些不标准的词汇来说明这个问题。
因为这样便于理解。我这里不解太多的理论,因为我自己现在也正在研究jvm
规范的,因为很多东西java和c++不同,虽然两者实现很相似。上面这点,
我是根据我个人的一些实践,包括理论方面和程序编写实践得到的。但是
我也不敢全部拿c++的那套实现讲给你听,实际上讲了你也不一定听得懂的。
我这里主要讲一些基本的知识,你记住就可以了的,等你学习深入的时候
我再给解释,也许那时候你自然就懂了。
实际上在继承以后,子类会重新设置自己的虚拟函数表,
这个虚拟函数表中的项目有由两部分组成。从父类继承的虚拟函数和子类自己
的虚拟函数。



记住一个很简单又很复杂的规则,一个类型引用只能引用引用类型自身含有的
方法和变量。你可能说这个规则不对的,因为父类引用指向子类对象的时候,
引用是子类的方法的。我告诉你这个规则对于这样的情况依然是成立的。放松
你的大脑,不要想一些乱七八糟的事情,仔细听我分析。



对了,到这里的时候我假设你对于上面的规则除了虚拟函数调用的情况下,
其他的静态函数引用,以及变量引用都明白了。



下面我们开始我们的重量级说明。虚拟函数引用。
下面是jvm规范中关于对象内存布局的说明,我没有翻译
我想你可以看明白,反正我现在看英文没有问题,
如果不明白就查字典。
The Java Virtual Machine does not require any particular internal
structure for objects. In Sun's current implementation of the Java
Virtual Machine, a reference to a class instance is a pointer
to a handle that is itself a pair of pointers: one to a table
containing the methods of the object and a pointer to the
Class object that represents the type of the object, and
the other to the memory allocated from the Java heap for
the object data.



根据这里我就知道实际上jvm关于多态性支持解决方法是和c++中几乎一样的,
只是c++中编译器很多是把类型信息和虚拟函数信息都放在一个虚拟函数表中,
但是利用某种技术来区别。



所以当你使用父类引用指向子类的时候,其实jvm已经使用了编译器产生的类型
信息调整转换了。这里你可以这样理解,相当于把不是父类中含有的函数从虚拟
函数表中设置为不可见的。注意有可能虚拟函数表中有些函数地址由于在子类中
已经被改写了,所以对象虚拟函数表中虚拟函数项目地址已经被设置为子类中完成
的方法体的地址了。



上面这一段就是为什么父类引用指向子类对象时候,有的方法可以调用,有的方法
却不能调用。



虚拟函数调用是经过虚拟函数表间接调用的,所以才得以实现多态的。

from: http://bbs.chinaunix.net/viewthread.php?tid=15929
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 是的,Java中的覆盖和重载都体现了多态性。 覆盖(Override)是在子类中重写父类中已有的方法,用子类的实现覆盖父类中的同名方法。在运行时,当调用该方法时,会根据实际对象的类型来确定调用的方法。这就是动态多态性的体现。 重载(Overload)是在一个类中定义多个同名的方法,但它们的参数类型或个数不同,这样在调用这些方法时,编译器会根据传递的参数类型和个数选择最合适的方法进行调用。这就是编译时多态性的体现。 Java中的覆盖和重载都是多态性的表现,但是它们的实现方式不同,覆盖是运行时多态性,而重载是编译时多态性。 ### 回答2: Java的覆盖和重载都是多态性在面向对象编程中的体现。 覆盖(Overriding)是指在子类中重新定义父类中已有的方法。子类通过覆盖可以改变父类方法的实现方式,但仍然保持方法名称和参数列表相同。当使用父类的引用指向子类对象时,调用该方法时会根据对象的实际类型来确定要执行的方法,体现了动态绑定。这种灵活的行为正是多态性的体现。 重载(Overloading)是指在一个类中定义多个具有相同名称但参数列表不同的方法。重载方法可以具有不同的参数类型、参数个数或参数顺序,但返回类型可以相同也可以不同。当调用重载方法时,编译器会根据实际传入的参数来决定要调用的具体方法,体现了静态绑定。重载能够提供更多的方法调用选择,增加了程序的灵活性和可读性。 通过覆盖和重载,Java实现了多态性多态性是面向对象编程的重要特征之一,它允许使用父类的引用来指向不同子类的对象,从而实现对不同对象的统一操作。多态性使得程序更加灵活、可扩展,并且减少了代码的重复性。 总之,Java的覆盖和重载通过提供不同的方法调用方式,体现了多态性的概念和特征。使用多态性的编程方式可以提高程序的灵活性、可读性和可维护性。 ### 回答3: Java的覆盖和重载是实现多态性的两种重要手段。Java中的一种类,可以在继承一个父类的同时,根据自身的需求对父类的某些方法进行覆盖。覆盖即子类对父类中同名方法的重新实现,子类可以根据自己的需要重新定义该方法的行为。这样,在使用父类引用指向子类对象时,通过调用被覆盖的方法,会根据实际的对象类型调用相应的实现,实现了多态性的特点。 另外一种实现多态性的方式是重载,Java中允许在一个类中定义多个同名的方法,只要它们的参数类型或参数个数不同。当程序调用这个方法时,编译器会根据传入的参数类型和个数来匹配对应的方法进行调用。重载的一个重要特点是方法名相同但参数不同,这样可以增加代码的复用性,不同的方法根据输入参数的类型或个数来选择执行适当的操作。 通过覆盖和重载,Java实现了多态性,使得不同类型的对象可以根据实际情况调用适当的方法。这种灵活性和扩展性可以提高代码的复用性和可维护性,同时也简化了程序的设计和开发过程。多态性是面向对象编程的重要特征之一,Java中的覆盖和重载就是多态性在语法层面的具体实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值