A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© HM张勇 高级黑马   /  2013-3-16 13:54  /  3052 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 HM张勇 于 2013-3-16 15:13 编辑

看毕老师继承的视频时,问自己一个问题。子类继承了父类后,如何在内存中分配空间的呢?分别如何指向对象的呢?



点评

如果你的问题得到解决,请及时将主题改为[已解决],如果还有问题请继续追问,谢谢  发表于 2013-3-16 14:55

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

7 个回复

倒序浏览
{:soso_e179:}这个问题问得好,好像在《Think in java》中有一段描述子类对象创建的时候子类和父类的加载顺数的问题,创建类对象的时候,先查看有没有父类,有的话再看父类有没有父类……知道追溯到最Object,然后从上到下将所有的类一次加载,最后加载当前类并创建器对象。所以子类和父类在内存中应该是鸽子有一块内存空间,然后子类和父类通过引用(指针)建立了联系。
坐等楼下上图以及精辟的答案
回复 使用道具 举报
实际上还是父类分配父类的内存空间,子类分配子类的内存空间。[子类只分配自己特有的成员的内存,其他的使用父类的,你要记注子类中有一个父类的指针,也就是引用Super,子类是通过super来找到自己的父类的。],最终合并到了一起,这里只是这么理解。

通过this.age和base.age使用同一个内存地址也可以看出,这种理论也可以解释为什么构造函数不能被继承,只能子类来调用父类的构造函数。
因为父类构造函数是要用来为父类分配内存空间,子类“调用”而非“继承”父类构造函数。然后在调用自己的构造函数。
如果子类重写父类的方法时,通过虚方法表来寻找子类的实现。在实例化子类对象时,是先构造父类的内存块,然后再构造子类的(子类相对于父类扩展了的那些)。
编译器的调用过程是先调用基类的构造函数,对派生类中的基类数据进行初始化,然后再调用派生类自己的构造函数,对派生类的数据进行初始化工作。
子类里有一个区域放的父类的实例,子类内存区里有一个this指针,指向了这个内存区里包括的父类实例区,
当把引用付给父类时,是把子类内存区里面的父类实例区域的引用给了父类的实例.

评分

参与人数 2技术分 +1 黑马币 +18 收起 理由
孙晋学 + 18 赞一个!
贾文泽 + 1

查看全部评分

回复 使用道具 举报
当程序创建一个一个子类对象时,系统不仅会为该类中定义的实例变量分配内存,也会为它从父类继承得到的所有实例变量分配内存。如果该对象的父类定义了2个实例变量,当前类定义了3个实例变量,那么这个Java对象会保存2+3个实例变量。(此处没有考虑他的间接父类的实例变量,如果有也要在当前类保存的。)
回复 使用道具 举报
如果有继承关系的话,分配内存空间是从最顶层的类开始实例化并分配的
回复 使用道具 举报
如果有继承关系的话,分配内存空间是从最顶层的类开始实例化并分配的
回复 使用道具 举报
我感觉你的问题有些太笼统,类只有创建对象的时候才会分配内存,
举个例子来说,人是一个类,那你说人放在哪?人本身就是个抽象代词,当把他定义为一个类,它有一些属性和功能,
比如说你,就是一个类为人的对象,对象是实际存在的,类更像是一些规则,只有当类创建出实际的对象时,这些规则才会起作用,
  1. class Person//定义一个类
  2. {
  3.          String name;//Person类的其中一个属性
  4.          int age;//Person类的另外一个属性
  5.          void speak()//Person类的一个功能
  6.          {
  7.                  System.out.println("我是一个功能,我会说你好");
  8.          }
  9.         void work()//Person类的另外一个功能
  10.         {
  11.          System.out.println("我是一个功能,我会干活");
  12.         }
  13. }
  14. class Student extends Person//Student类继承了Person类
  15.              //现在Student类有三个属性,两个方法,
  16.                          //但是注意,子类的work()把父类的隐藏了,
  17.                          //也就是子类对象调用work()时,显示的是学习。
  18.                          //但父类的work()也分配内存。
  19. {
  20.          String num;//子类独有的属性
  21.          void work()//子类重写了父类的work(),让功能更具体。
  22.          {
  23.          System.out.println("我是一个功能,我会学习");
  24.          }
  25. }
  26. class Demo
  27. {        public static void main(String[] args) //主函数,也就是程序执行的开始
  28.         {
  29.                 Student p=new Student();//创建一个学生的对象,此时才分配内存
  30.                 p.name="liming";//给对象属性赋了具体值
  31.                 p.num="0214";
  32.                 System.out.println("我的名字是"+p.name);
  33.                 System.out.println("我的学号是"+p.num);
  34.                 p.work();//利用对象实现work()功能
  35.         }
  36. }
复制代码
分别如何指向对象的呢?
你这个问题不算是正确的问题,谁指向对象?建一个对象时,对象对应着内存,靠内存地址,像上面的程序,p对象靠指针来实现操作自己的属性和功能
也就是一个内存中的地址,内存就好比是一间间屋子,地址就是门牌号,你是一个学生对象,你所有的属性和方法都装在了8号房间
,你的手里有一个8号房间牌,只要想获取你的任何信息,都要去8号房间取。
我是这样理解你的问题的,如果你是想问具体的物理内存分配情况,那我只能用这么一个问题回答你:
你去银行存钱,你说你的钱到底存在银行那个具体位置,
你知道知道你的钱在银行就行了,没必要知道具体哪个保险哪一层第几张钱是你的。

评分

参与人数 1技术分 +1 收起 理由
洪建超 + 1

查看全部评分

回复 使用道具 举报
子类继承父类之后,原来怎么分别还是怎么分配,并不会随着继承而改变空间,讨论这个没多大意义,最重要的还是子父类的对象的引用是怎么用的,即this和super的用法
如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this
子类要访问父类中的同名变量,用super。
this代表本类的引用,super代表父类的引用
还要就是要记住子类的实例化过程:子类的所有的构造函数,默认都会访问父类中空参数的构造函数。
因为子类每一个构造函数内的第一行都有一句隐式super();
当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。
子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。
子类中至少会有一个构造函数会访问父类中的构造函数。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马