由于ZangXT对这个问题提出了质疑, 所以, 在文末, 又追加了一个测试使用super绕过多态的例子, 以期证明, 构造一个对象的时候, 隐含的持有了父类的引用(或者以更合适的名词称呼: 向上代理)
- package test1;
- /**
- *
- * @author leslie
- */
- class MyA {
- int a = 1;
- public MyA() {
- print();
- }
- public void print() {
- System.out.println("aaa" + a);
- }
- }
- class MyB extends MyA {
- int a = 2;
- public MyB() {
- print();
- }
- public void print() {
- System.out.println("bbb" + a);
- }
- }
- class MyC extends MyB {
- int a = 3;
- public MyC() {
- print();
- }
- public void print() {
- System.out.println("ccc" + a);
- }
- }
- public class Main {
- /**
- * @param args the command line arguments
- */
- public static void main(String[] args) {
- new MyC();
- }
- }
- 这个程序在netbean下返回的是:
- ccc0
- ccc0
- 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(), 就能看到区别了.
父类的代码
- public class A {
- public void m() {
- System.out.println("This is A");
- }
- }
子类的代码:
- public class B extends A {
- @Override
- public void m() {
- System.out.println("This is B");
- }
- public void f() {
- super.m();
- }
- }
测试代码:
- public class Test {
- /**
- * @param args
- */
- public static void main(String[] args) {
- B b = new B();
- b.f();
- }
- }