知识点:
子类继承父类之后,实例化子类时,内存中子类是如何分配内存的呢?
下面,自己会结合一个例子,解释一下,一个子类实例化过程中,内存是如何分配的
参考博客:http://www.cnblogs.com/xdp-gacl/p/3635948.html
(1)代码例子
//动物 public class Animal{ public String name;//名称 public int age;//年龄 public Animal(){ this.age=100; System.out.println("动物无参构造函数!"); } //展示动物属性方法 public void showInfo(){ this.name="动物名"; System.out.println("Animal.name:"+this.name); } }
//人 public class Person extends Animal { public String name;//名称 public Person(){ System.out.println("人无参构造函数!"); } //展示(动物)人类属性方法 @Override public void showInfo(){ super.showInfo();//调用父类的方法,给Animal的name赋值并输出 this.name="人名"; System.out.println("Animal.age:"+super.age);//输出父类的age值 System.out.println("Person.name:"+this.name);//输出Person实例的name值 } }
//测试类 public class Test { public static void main(String[] args) { Person p=new Person(); p.showInfo(); } } 运行结果: (2)子类实例化过程中的内存分配 针对于上面的例子,分析一下内存分配 执行main方法中的第一句:
Person p=new Person(); 先在栈(stack)空间中产生一个变量p,变量p里面存放的值是,Person类new的实例化对象的堆地址,通过这个值就可以找到堆中new对象的值,因为Person类是继承Animal父类的子类,所以在new Person对象时,这个对象里包含了Animal对象,Animal的name属性声明是没有初始化值,在程序编译时,会默认赋值null(String类型为null,int类型是0),Animal的age属性,在调用Person类的构造方法时,会先调用父类的无参构造函数,并给age赋值为100,同理Person类对象自己的属性name值为null,因此在执行Person p=new Person();之后,虚拟机中的内存分配 如下: 执行第二句话
p.showInfo(); 我们在new一个对象时,这个对象如果是继承一个父类,那么在堆中会产生一个this和一个super引用,this引用指向这个子类对象本身,super引用则指向子类包含的父类对象,如何没有继承父类,则仅仅只有this引用。当执行p.showInfo();时,进入Person类的showInfo()方法,开始会通过super引用,调用父对象的 showInfo();的方法,将父对象的name值变成“动物名”并打印,然后通过this引用调用子类自己的name属性并赋值“人名”,然后打印自己的name值,父对象的age(100)值,这是内存如下:
结合内存分析,上面打印结果,就一目了然啦!