下面正式开始我们今天的话题,正对你的问题我进行解释,
这里我尽可能的解释详细一点让你明白,实际上这里太复杂
涉及到oop的具体实现问题,这个问题又不得不涉及到编译器
问题,主要的又是对象内存布局问题。
由于第二个问题比较简单,我把回答问题的次序颠倒一下。
*********
问题二
*********
你说的很对,我这里解的是继承,但是我这里解的不仅仅是继承的
问题。可以这样是你说的继承只是我解释动态性问题的一个途径和
手段而已,因为继承和多态性一样是面向对象中很重要的概念,不
是写一点文章就可以说明白的。
简单一点和不精确的说,动态性与是继承不可分割的,如果没有继承
根本就谈不上多态性的。所以我说你说的对,但是你没有真正明白我
例子的作用(55555555~~~~~~~~~~~~~我的心血呀)
*********
问题一
*********
首先需要说明的是你对这个问题的理解是不正确的。
这个问题更是复杂的一塌糊涂,我尽量用一些不标准的词汇来说明这个问题。
因为这样便于理解。我这里不解太多的理论,因为我自己现在也正在研究jvm
规范的,因为很多东西java和c++不同,虽然两者实现很相似。上面这点,
我是根据我个人的一些实践,包括理论方面和程序编写实践得到的。但是
我也不敢全部拿c++的那套实现讲给你听,实际上讲了你也不一定听得懂的。
我这里主要讲一些基本的知识,你记住就可以了的,等你学习深入的时候
我再给解释,也许那时候你自然就懂了。
实际上在继承以后,子类会重新设置自己的虚拟函数表,
这个虚拟函数表中的项目有由两部分组成。从父类继承的虚拟函数和子类自己
的虚拟函数。
记住一个很简单又很复杂的规则,一个类型引用只能引用引用类型自身含有的
方法和变量。你可能说这个规则不对的,因为父类引用指向子类对象的时候,
引用是子类的方法的。我告诉你这个规则对于这样的情况依然是成立的。放松
你的大脑,不要想一些乱七八糟的事情,仔细听我分析。
对了,到这里的时候我假设你对于上面的规则除了虚拟函数调用的情况下,
其他的静态函数引用,以及变量引用都明白了。
下面我们开始我们的重量级说明。虚拟函数引用。
下面是jvm规范中关于对象内存布局的说明,我没有翻译
我想你可以看明白,反正我现在看英文没有问题,
如果不明白就查字典。
the java virtual machine does not require any particular internal
structure for objects. in suns 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已经使用了编译器产生的类型
信息调整转换了。这里你可以这样理解,相当于把不是父类中含有的函数从虚拟
函数表中设置为不可见的。注意有可能虚拟函数表中有些函数地址由于在子类中
已经被改写了,所以对象虚拟函数表中虚拟函数项目地址已经被设置为子类中完成
的方法体的地址了。
上面这一段就是为什么父类引用指向子类对象时候,有的方法可以调用,有的方法
却不能调用。
虚拟函数调用是经过虚拟函数表间接调用的,所以才得以实现多态的。