靜態塊:用static申明,JVM加載類時執行,僅執行一次函數
構造塊:類中直接用{}定義,每一次建立對象時執行spa
public class Study_static { public static char text = 'a'; //靜態對象 public Study_static(){ //構造函數 System.out.println('c'); } { //構造塊 System.out.println('b'); } static{ //靜態塊 System.out.println(text); } public static void main(String[] args){ Study_static a = new Study_static(); } }
輸出結果:code
執行順序優先級:靜態塊>main()>構造塊>構造方法對象
因此先執行靜態塊,再tudy_static a = new Study_static();該語句建立對象,則又會調用構造塊,輸出構造塊,再執行構造函數。blog
然而,這裏的靜態塊,並非僅僅靜態塊,而是靜態域,包含了靜態變量,靜態塊,這二者的執行順序就是按照位置順序進行。繼承
總結:內存
1.靜態塊其實就是給類初始化的,而構造代碼塊是給對象初始化的。class
2.靜態代碼塊只會運行一次變量
3.靜態塊中的變量是局部變量,與普通函數中的局部變量性質沒有區別。
一個類中能夠有多個靜態代碼塊,執行順序按照位置決定。
構造函數
分析:
由於靜態部分是依賴於類,而不是依賴於對象存在的,因此靜態部分的加載優先於對象存在。
當找到main方法後,由於main方法雖然是一個特殊的靜態方法,可是仍是靜態方法,此時JVM會加載main方法所在的類,試圖找到類中其餘靜態部分,即首先會找main方法所在的類。
執行順序大體分類:
1.靜態屬性,靜態方法聲明,靜態塊。
2.動態屬性,普通方法聲明,構造塊。
3.構造方法。
1.1 靜態:
當加載一個類時,JVM會根據屬性的數據類型第一時間賦默認值(一舉生成的)。而後再進行靜態屬性初始化,併爲靜態屬性分配內存空間,靜態方法的聲明,靜態塊的加載,沒有優先級之分,按出現順序執行,靜態部分僅僅加載一次。至此爲止,必要的類都已經加載完畢,對象就能夠被建立了。
1.2 普通:
當new一個對象時,此時會調用構造方法,可是在調用構造方法以前,(此刻1.1已經完成,除非被打斷而暫停)執行動態屬性定義並設置默認值(一舉生成的)。而後動態屬性初始化,分配內存,構造塊,普通方法聲明(只是加載,它不須要初始化,只有調用它時才分配內存,當方法執行完畢後內存當即釋放),沒有優先級之分,按出現順序執行。最後進行構造方法中賦值。當再次建立一個對象,再也不執行靜態部分,僅僅重複執行普通部分。
注意:若是存在繼承關係,建立對象時,依然會首先進行動態屬性進行定義並設默認值,而後父類的構造器纔會被調用,其餘一切都是先父類再子類(由於子類的static初始化可能會依賴於父類成員可否被正確初始化),若是父類還有父類,依次類推,無論你是否打算產生一個該父類的對象,這都是天然發生的。
總結:只要按照這個步驟,遇到這一類問題就能夠解決了。
1-3:類加載過程,不涉及構造方法
1-5: 實例化過程,涉及構造方法
1.類中全部屬性的默認值(一舉而成)
2. 父類靜態屬性初始化,靜態塊,靜態方法的聲明(按出現順序執行)
3. 子類靜態屬性初始化,靜態塊,靜態方法的聲明 (按出現順序執行)
4. 調用父類的構造方法,
首先父類的非靜態成員初始化,構造塊,普通方法的聲明(按出現順序執行)
而後父類構造方法
5. 調用子類的構造方法,
首先子類的非靜態成員初始化,構造塊,普通方法的聲明(按出現順序執行)
而後子類構造方法