先上代码:
class Parent
{
int x = 10;
public Parent()
{
add(2);
}
void add(int y)
{
x += y;
}
}
class Child extends Parent
{
int x = 9;
void add(int y)
{
x += y;
}
public static void main(String[] args)
{
Parent p = new Child();
System.out.println(p.x);
}
}
上面这段代码很简单,输出了10。为什么呢?
下面简要介绍下调用过程。
首先加载这段代码,代码全部放进内存方法区内。然后new Child(),因为Child继承Parent,所以首先实例化Parent。
父类中x=10 ,然后调用父类构造函数,父类构造函数调用了add函数。注意在这个时候代码已经全部放进了方法区,所以子类的add函数在内存中是存在的,所以子类add函数覆盖了父类的add函数。
调用了子类的add函数,里面有一个x,这个x是父类还是子类的呢?
是子类的,因为子类有一个x的成员变量。这时候子类的x+=2,那等于多少呢?
等于2!因为子类还没有进行实例化,所以子类中int x = 9也就是给x赋值为9的这句话还没有执行,所以系统默认子类中x为0, 0+2=2,所以子类中x为2.但是记住这里改变的只是子类中的x,父类是没有影响的,也就是说父类中的x仍然是10!
好了,接下来进行子类的实例化,这没有什么好说的了,最后子类中x为9,因为int x = 9把x的值从2改为了9了。
最后Parent p = new Child(),p是父类的引用,所以p.x输出的是父类的值也就是10.
解析完毕。
上面的解析是比较粗糙的,但是基本过程是正确的。至于在堆,栈,方法区里面的那些详细的事情,我们还得要仔细研究。