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

14 篇文章 0 订阅

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

 

 

 

[java]  view plain copy
  1. package test1;   
  2.   
  3. /**  
  4.  
  5. * @author leslie  
  6. */   
  7.   
  8. class MyA {   
  9. int a = 1;   
  10. public MyA() {   
  11. print();   
  12. }   
  13.   
  14. public void print() {   
  15. System.out.println("aaa" + a);   
  16. }   
  17. }   
  18.   
  19. class MyB extends MyA {   
  20. int a = 2;   
  21. public MyB() {   
  22. print();   
  23. }   
  24.   
  25. public void print() {   
  26. System.out.println("bbb" + a);   
  27. }   
  28. }   
  29.   
  30. class MyC extends MyB {   
  31. int a = 3;   
  32. public MyC() {   
  33. print();   
  34. }   
  35.   
  36. public void print() {   
  37. System.out.println("ccc" + a);   
  38. }   
  39. }   
  40.   
  41.   
  42. public class Main {   
  43.   
  44.     /**  
  45.     * @param args the command line arguments  
  46.     */   
  47.     public static void main(String[] args) {   
  48.         
  49. new MyC();   
  50.   
  51. }   
  52. }   
  53. 这个程序在netbean下返回的是:   
  54. ccc0   
  55. ccc0   
  56. 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. public class A {  
  2.     public void m() {  
  3.         System.out.println("This is A");  
  4.     }  
  5. }  

 

子类的代码:

[java]  view plain copy
  1. public class B extends A {  
  2.   
  3.     @Override  
  4.     public void m() {  
  5.         System.out.println("This is B");  
  6.     }  
  7.       
  8.     public void f() {  
  9.         super.m();  
  10.     }  
  11.       
  12. }  

 

测试代码:

[java]  view plain copy
  1. public class Test {  
  2.   
  3.     /** 
  4.      * @param args 
  5.      */  
  6.     public static void main(String[] args) {  
  7.         B b = new B();  
  8.         b.f();  
  9.     }  
  10.   
  11. }  

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值