Java继承关系、构造器的内存分析

由于ZangXT对这个问题提出了质疑, 所以, 在文末, 又追加了一个测试使用super绕过多态的例子, 以期证明, 构造一个对象的时候, 隐含的持有了父类的引用(或者以更合适的名词称呼: 向上代理)

[java] view plain copy
  1. packagetest1;
  2. /**
  3. *
  4. *@authorleslie
  5. */
  6. classMyA{
  7. inta=1;
  8. publicMyA(){
  9. print();
  10. }
  11. publicvoidprint(){
  12. System.out.println("aaa"+a);
  13. }
  14. }
  15. classMyBextendsMyA{
  16. inta=2;
  17. publicMyB(){
  18. print();
  19. }
  20. publicvoidprint(){
  21. System.out.println("bbb"+a);
  22. }
  23. }
  24. classMyCextendsMyB{
  25. inta=3;
  26. publicMyC(){
  27. print();
  28. }
  29. publicvoidprint(){
  30. System.out.println("ccc"+a);
  31. }
  32. }
  33. publicclassMain{
  34. /**
  35. *@paramargsthecommandlinearguments
  36. */
  37. publicstaticvoidmain(String[]args){
  38. newMyC();
  39. }
  40. }
  41. 这个程序在netbean下返回的是:
  42. ccc0
  43. ccc0
  44. ccc3

问题就是上面写的这样,下面是内存分析.

执行new MyC();时候的调用顺序.
1. ClassLoader加载MyC这个类.
2. 准备调用MyC的构造方法.
3. 准备调用MyC的父类MyB的构造方法.
4. 准备调用MyB的父类MyA的构造方法.
5. 准备调用MyA的父类java.lang.Object的构造方法.
6. 执行java.lang.Object的构造方法.
7. 初始化MyA类的成员变量,a=1;
注意:此时堆栈中对象的分布是MyC的对象持有MyB对象的一个引用,MyB对象持有MyA对象的一个引用,MyA对象持有java.lang.Object对象的一个引用,MyA,MyB,MyC对象中各有一个成员变量a,一定注意,这个时候,堆栈中有三个a,此时MyA的成员变量a=1;MyB和MyC的成员变量a=0;
8. 执行MyA的构造方法,调用print方法
注意:这里有多态,我们调用的方法实际上是MyC对象重写的方法,也就是说内存代码区向外提供调用的print方法是MyC的print方法,由于MyC中的成员变量a=0,所以此时打印 "ooo0 ";
9. 初始化MyB的成员变量.和第7条同理,此时堆栈中MyA的a=1,MyB的a=2,MyC的a=0;
10. 执行MyB的构造方法.和8同理,调用的还是MyC的print方法,所以打印的是 "ooo0 ";
11. 初始化MyC的成员变量.和第7条同理,此时堆栈中MyA的a=1,MyB的a=2,MyC的a=3;
12. 执行MyC的构造方法.和8同理,调用的是MyC的print方法,此时MyC的成员变量a=3,所以打印的是 "ooo3 ";

做这个内存分析的时候,主要考虑new MyC();这一句执行的过程:
1. ClassLoader加载MyC;
2. 进入MyC的构造器,首先构造MyC的父类,直到Object,Object之后怎么处理就不清楚了.
3. 处理完父类构造器之后,处理成员变量的初始化.
4. 然后执行构造器中的代码.

相关的东西:
多态:一个类继承关系中的重写的方法,在调用的时候,只有一个,那就是重写了那个方法的备份最小的类中的方法体.

以下是试图证明存在super引用的代码. 感兴趣的朋友可以把子类B中的f()方法中的super.m()换成this.m(), 就能看到区别了.

父类的代码

[java] view plain copy
  1. publicclassA{
  2. publicvoidm(){
  3. System.out.println("ThisisA");
  4. }
  5. }

子类的代码:

[java] view plain copy
  1. publicclassBextendsA{
  2. @Override
  3. publicvoidm(){
  4. System.out.println("ThisisB");
  5. }
  6. publicvoidf(){
  7. super.m();
  8. }
  9. }

测试代码:

[java] view plain copy
  1. publicclassTest{
  2. /**
  3. *@paramargs
  4. */
  5. publicstaticvoidmain(String[]args){
  6. Bb=newB();
  7. b.f();
  8. }
  9. }

转自:http://blog.csdn.net/lgg201/article/details/4061041

你可能感兴趣的:(java)