class Depend
{
int i = 10;
public Depend()
{
print();
i = 20;
}
void print()
{
System.out.println("Depend=> " + i);
}
}
public class Qdb extends Depend
{
int i = 30;
public Qdb()
{
print();
super.print();
i = 40;
}
void print()
{
System.out.println("Target=> " + i);
}
public static void main(String[] args)
{
new Qdb();
}
}
回答:
初始化順序是:
父類成員變量,父類構造函數,子類成員變量,子類構造函數
我們順着初始化的順序來說
首先程序從main方法開始執行,new Qdb(),這句話就是要new一個Qdb的對象,根據對象初始化的順序,初始化子類之前必須要初始化父類,所以此時一系列的調用開始了
1,調用Qdb的父類Depend類的構造函數,在調用構造函數之前,成員變量是先於構造函數初始化的,這個時候Depend裏面的i已經有值了,它的值就是10,在Depend構造函數裏面,我們看到的第一句是:print方法,這個print方法我們要注意,它在Depend的子類也定義了,並且此次初始化是由子類Qdb發起的,所以實際上這個print方法調用的是Qdb裏面定義的print,而這個時候有意思的事情就出現了,此時子類還沒有出生呢,因爲這個時候父類才正在構造之中,所以子類中此時的i還是0,而print正好打印出的是子類的i,所以第一次輸出是0;
2,父類調用完子類的print後,把父類的i賦了值20,此時父類已經完全被構造出來了,馬上就要開始構造子類了.
3,同理,在調用子類的構造函數之前,子類的i被賦了初值30,然後進入子類的構造函數,此時調用的也是print,這個就非常好理解了,這個print肯定是子類自己的print方法了,此時i已經構造好,當然,此時輸出的值是30;
4,下一句super.print(),這句話顯示的調用了父類的print方法,而此時父類的i已經在父類的構造函數裏面改爲20了,所以此次調用輸出20.
5,然後再把子類的i的值設爲50.
在以上過程中,如果掌握好了類的初始化順序,是比較容易知道輸出結果的.還有一點要記住,JAVA裏面的方法是動態綁定的,而成員卻是靜態綁定的.父類裏面調用的print之所以會輸出0,就是因爲print實際上調用的是子類的print,因爲整個這場調用都是由new Qdb()這句話產生的.
摘自:http://topic.csdn.net/u/20080619/19/924c55b0-5919-46ad-8bf0-0c6425020253.html?seed=1780906883
這裏對第3步不理解,如果說i已經被int i = 30;聲明爲int,爲什麼還沒賦值呢?
如果沒被聲明,又爲什麼會輸出 0 呢?
難道說,子類成員變量的聲明在父類構造函數之前,而賦值在父類構造函數之後?