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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

  1. class Base{
  2.         //定义一个名为i的实例变量
  3.         private int i = 2;
  4.         public Base(){
  5.                 this.display();
  6.         }
  7.        
  8.         public void display(){
  9.                 System.out.println(i);
  10.         }
  11.        
  12. }

  13. //继承Base的Derived子类
  14. class Derived extends Base{
  15.         //定义一个名为i的实例变量
  16.         private int i = 22;
  17.        
  18.         //构造器,将实例变量i初始化为222
  19.         public Derived(){
  20.                 i = 222;
  21.         }
  22.        
  23.         public void display(){
  24.                 System.out.println(i);
  25.         }
  26. }

  27. public class Test {
  28.        
  29.         public static void main(String[] args) {
  30.                 //创建Derived的构造器创建实例
  31.                 new Derived();
  32.         }
  33. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
MVP + 1

查看全部评分

4 个回复

倒序浏览
这里面涉及到了多态和初始化顺序。这部分我理解的不透彻,我就先说说我的理解吧。首先会加载主函数所在的类Test,当运行到new Derived的时候会去加载Derived类,此时虚拟机发现Derived类有父类,就先加载父类Base并对Base类的变量i进行初始化,接着执行Base的构造函数,调用display()方法。但此时由于多态的原因,display其实是子类中的display,但因为子类中的变量还没进行显示初始化,所以i是0。这是我的理解,期待大神给予指正。

评分

参与人数 1技术分 +1 收起 理由
MVP + 1

查看全部评分

回复 使用道具 举报
本帖最后由 王世虎 于 2014-11-14 01:36 编辑

先说下主函数中使用new Derived();创建一个类会在内存中做出以下动作
1.先把字节码文件*.class文件加载进内存中。
2.方法和静态属性定义在方法区中。
3.静态代码块初始化(有的话)
4.在堆内存中开辟空间,分配地址值。
5.在堆内存中创建对象,并进行默认初始化。
6.对属性进行显示初始化。
7.构造代码块初始化。
8.构造函数初始化。
9.内存地址值分配给类变量。
(此处借鉴)
因为Derived类继承了 Base类   所以值得注意的是:
在第8步构造函数初始化的时候,
构造函数的第一行会有一个默认的访问父类构造函数方法:super();
因为子类复写了父类中的display()方法,此时父类Base构造函数,调用的display()方法,是子类的方法。
而此时子类构造函数的下一句 i = 222,还没有执行到。
子类构造函数如下:
public Derived()
{   
       super(); //默认访问父类空参数的构造函数
         i = 222;
}

如果把主函数的 new Derived();换成Derived d = new Derived();然后在调用d.display();或者是子类不复写父类的display()方法,那么结果又是不同的。

回复 使用道具 举报
上面两个回答的很详细,听你们解释后,感觉是那么一回事....估计我还得补补课..
回复 使用道具 举报
因为调用方法先从子类中找,因为子父类在栈中方法区中,子类会引向父类
C:\Documents and Settings\Administrator\桌面\图片1.png
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马