黑马程序员技术交流社区
标题:
帮忙解释下,这个程序的执行结果为什么是0?
[打印本页]
作者:
qq272936993
时间:
2014-11-13 21:47
标题:
帮忙解释下,这个程序的执行结果为什么是0?
class Base{
//定义一个名为i的实例变量
private int i = 2;
public Base(){
this.display();
}
public void display(){
System.out.println(i);
}
}
//继承Base的Derived子类
class Derived extends Base{
//定义一个名为i的实例变量
private int i = 22;
//构造器,将实例变量i初始化为222
public Derived(){
i = 222;
}
public void display(){
System.out.println(i);
}
}
public class Test {
public static void main(String[] args) {
//创建Derived的构造器创建实例
new Derived();
}
}
复制代码
作者:
DamonZh
时间:
2014-11-13 22:16
这里面涉及到了多态和初始化顺序。这部分我理解的不透彻,我就先说说我的理解吧。首先会加载主函数所在的类Test,当运行到new Derived的时候会去加载Derived类,此时虚拟机发现Derived类有父类,就先加载父类Base并对Base类的变量i进行初始化,接着执行Base的构造函数,调用display()方法。但此时由于多态的原因,display其实是子类中的display,但因为子类中的变量还没进行显示初始化,所以i是0。这是我的理解,期待大神给予指正。
作者:
王世虎
时间:
2014-11-14 01:33
本帖最后由 王世虎 于 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()方法,那么结果又是不同的。
作者:
qq272936993
时间:
2014-11-14 14:02
上面两个回答的很详细,听你们解释后,感觉是那么一回事....估计我还得补补课..
作者:
zhangyangLengen
时间:
2014-11-14 15:55
因为调用方法先从子类中找,因为子父类在栈中方法区中,子类会引向父类
C:\Documents and Settings\Administrator\桌面\图片1.png
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2