普通初始化塊(負責對象執行初始化)
- 沒有任何修飾詞,沒有任何名字,只有一對 {} ,多個普通塊會按普通塊的順序先後執行,而且優先於構造方法(器)執行。
- 定義多個普通初始化塊其實沒有意義,所有塊最終都是要執行的,所以儘可能的合併一個即可,可讀性更好。
- 當一個類加載後,系統爲對象實例變量分配內存的時候。順序:先執行初始塊 或者 聲明實例變量初始值(兩者優先級相同,看誰在前面先執行誰)
- 如果一個構造器中,有一些無需參數的初始化行爲(無參方法…),就可以把他們放在初始化塊中去
- 實際上,使用javac編譯java類後,初始化代碼會進入每一個構造器中,並且位於構造器所有代碼的前面。所以當創建一個對象的時候,系統會一直往上查找直到object類,然後再從object類的初始化塊、構造器依次往下執行,最後纔到該類的初始化塊和構造器。
靜態初始化塊(負責類執行初始化)
- 優先於普通初始化塊執行
當在主類中new兩個子類的子類對象,代碼的執行順序:
1,首先從object的靜態初始化塊開始依次加載,因爲要先加載類,一旦加載類就會加載靜態初始化塊。
2,加載完類後,依次從object類往下加載普通代碼塊和構造器(無參+有參)
3,加載完第一個對象以後,記載第二個對象的時候不再會調用static代碼塊,static代碼塊只在加載類的時候加載,所以從加載普通代碼塊開始了。
class Root
{
static{
System.out.println("father的靜態初始化塊");
}
{
System.out.println("father的普通初始化塊");
}
public Root()
{
System.out.println("father的無參數的構造器");
}
/*public Root(String msg) {
System.out.println("Root的帶參數構造器,其參數值:"
+ msg);
}*/
}
class Mid extends Root
{
static{
System.out.println("son的靜態初始化塊");
}
{
System.out.println("son的普通初始化塊");
}
public Mid()
{
System.out.println("son的無參數的構造器");
}
public Mid(String msg)
{
// 通過this調用同一類中重載的構造器
this();
System.out.println("son的帶參數構造器,其參數值:"
+ msg);
}
}
class Leaf extends Mid
{
static{
System.out.println("son_son的靜態初始化塊");
System.out.println("============================");
}
{
System.out.println("son_son的普通初始化塊");
System.out.println("============================");
}
public Leaf()
{
// 通過super調用父類中有一個字符串參數的構造器
super("瘋狂Java講義");
System.out.println("執行son_son的構造器");
}
}
public class Demo06_instanceof
{
public static void main(String[] args)
{
new Leaf();
//System.out.println("============================");
new Leaf();
}
}
執行結果:
father的靜態初始化塊
son的靜態初始化塊
son_son的靜態初始化塊
============================
father的普通初始化塊
father的無參數的構造器
son的普通初始化塊
son的無參數的構造器
son的帶參數構造器,其參數值:瘋狂Java講義
son_son的普通初始化塊
============================
執行son_son的構造器
father的普通初始化塊
father的無參數的構造器
son的普通初始化塊
son的無參數的構造器
son的帶參數構造器,其參數值:瘋狂Java講義
son_son的普通初始化塊
============================
執行son_son的構造器