研究問題:
- 構造方法,成員變量的初始化,多態構造函數調用時機?
要點:
- java 構造函數 成員函數初始化順序 以及多態的構造函數的調用順序
http://blog.csdn.net/zhanghaotian2011/article/details/9040935 - class文件中先執行main方法外部靜態代碼塊,再按照順序依次執行其他代碼塊(構造代碼塊、局部代碼塊),main方法中類實例化對象時,它並不是首先調用其構造方法而是先是變量的初始化,而且成員的初始化的順序以成員變量的定義順序有關,先定義的先初始化,初始化後再調用構造方法。其實成員變量的初始化,在類的所有方法調用之前進行,包括構造方法。
注意:static 的成員比普通的成員變量先初始化。 ———————————————–混混哥—————————————————-
類初始化的時機,有且僅有四個:
1、遇到new、getstatic、putstatic、invokestatic這四條字節碼指令的時候。
2、使用Java.lang.reflect進行反射調用的時候。
3、當初始化一個類的時候,發現其父類還沒有初始化,那麼先去初始化它的父類。
4、當虛擬機啓動的時候,需要初始化main函數所在的類。———————————————-友誼哥———————————————–
說到這裏,還要說下,靜態變量和靜態初始化塊,普通變量、普通初始化塊之間的初始化順序。看這裏
鏈接中說明了,靜態變量和靜態初始化塊的聲明順序決定了初始化的順序。
靜態變量和靜態初始化塊的初始化時間::早於::普通變量和普通初始化塊::早於::構造方法。
並不是完全父類初始化完畢之後,子類纔開始初始化。實際上子類的靜態變量和靜態初始化塊的初始化是在父類的變量、初始化塊和構造器初始化之前就完成了。
截圖展示區:
-
1.
class Test01{
public Test01(int i){
System.out.println("Test01 of constractor : " + i);
}
}
public class Test02{
private Test01 t1 = new Test01(1);
private int n = 10;
public Test02(){
System.out.println("Test02 of constructor : " + n);
}
private Test01 t2 = new Test01(2);
public static void main(String[] args){
Test02 test = new Test02();
}
}
運行結果:
2.
public class Test03{
private int i1 = printCommon();
private static int i2 = printStatic();
public Test03(){
}
public static int printCommon(){
System.out.println("i1 is init!");
return 1;
}
public static int printStatic(){
System.out.println("i2 is init!");
return 2;
}
public static void main(String[] args){
Test03 t = new Test03();
}
}
運行結果:
-
3.
public class Test04{
private static Test04 t1 = new Test04();
private static int i1;
private static int i2 = 2;
public Test04(){
i1++;
i2++;
}
public static void main(String[] args){
Test04 t2 = new Test04();
System.out.println("t2.i1 = " + t2.i1);
System.out.println("t2.i2 = " + t2.i2);
}
}
運行結果:
4.
在類初始化的時候,就規定了,靜態語句塊中只能訪問到定義在靜態語句塊之前的變量,定義在它之後的,只能賦值,不能訪問。