淺析普通程式碼塊、構造程式碼塊、靜態程式碼塊
初次學習程式碼塊、構造程式碼塊、靜態程式碼塊後,決定寫此文章特別總結一下學習成果,本文用最淺顯的語言講述程式碼塊,若有錯誤請大神們指出,十分感謝(鞠躬)
1.普通程式碼塊
存在於方法中,用{}括起來
這種程式碼塊稱為普通程式碼塊,與平時語句執行無異,順序執行即可
public class A{ public static void main(String[] args){ { System.out.println("我是第一個普通程式碼塊"); } System.out.println("普通程式碼塊和普通語句沒區別"); { System.out.println("我是第二個普通程式碼塊"); } } } /* 執行結果: 我是第一個普通程式碼塊 普通程式碼塊和普通語句沒區別 我是第二個普通程式碼塊 */
2.構造程式碼塊
存在於類體中,用{}括起來
每次建立物件時都會呼叫,且構造程式碼塊先於構造方法執行,注意!若構造程式碼塊在main方法所在類中, main方法沒有對本類new物件,構造程式碼塊不會執行,因為此時物件還沒建立,main方法之所以能呼叫是因為static關鍵字的緣故,即使沒有new物件,jvm也可以通過類名呼叫!(具體可查閱main方法為什麼用public static void修飾)
具體區別請看如下程式碼
此時 main方法中有語句new B2();
public class B2{
public static void main(String[] args){
System.out.println("main方法被執行");
new B();
}
public B2(){
System.out.println("構造方法被執行");
}
{
System.out.println("構造程式碼塊被執行");
}
}
/*
執行結果:
main方法被執行
構造程式碼塊被執行
構造方法被執行
*/
下面我們將語句new B2刪去
public class B2{
public static void main(String[] args){
System.out.println("main方法被執行");
//new B2();
}
public B2(){
System.out.println("構造方法被執行");
}
{
System.out.println("構造程式碼塊被執行");
}
}
/*
執行結果:
main方法被執行
*/
輸出結果僅有“main方法被執行”
由此可見,若需要在main方法所在類執行構造程式碼塊,需要在main方法中new main方法所在類的物件
3.靜態程式碼塊
存在於方法之中,並被static修飾,及{}括起來
形如static{
}
靜態程式碼塊隨著類的載入而執行,因此靜態程式碼塊只執行一次(class檔案只加載一次),當編譯完畢後,通過jvm解釋class檔案時,main方法所在類首先被載入進方法區,並檢視有無父類.
若有 則 (1)父類靜態變數進行預設初始化 如若類體中有語句static int a = 1; 則預設初始化a為0
(2)父類靜態變數進行顯示初始化 如若類體中有語句static int a = 1; 則顯示初始化a為1
(3)執行父類靜態程式碼塊
(4)子類靜態變數進行預設初始化
(5)子類靜態變數進行顯示初始化
(6)執行子類靜態程式碼塊
(7)執行子類的main方法(假設此時main方法有對本類new物件 另:若沒有則在此步驟截止)
(8)父類非靜態變數進行預設初始化
(9)父類非靜態變數進行顯示初始化
(10)執行父類構造程式碼塊
(11)執行父類的構造方法
(12)子類的非靜態變數進行預設初始化
(13)子類的非靜態變數進行顯示初始化
(14)執行子類的構造程式碼塊
(15)執行子類的構造方法
具體程式碼如下所示
class B{
static int a = 1;
int a2 = 2;
static
{
System.out.println("父類static變數"+a);
System.out.println("父類靜態程式碼塊");
}
public B(){
System.out.println("父類構造方法被執行");
}
{
System.out.println("父類非static變數"+a2);
System.out.println("父類構造程式碼塊");
}
}
class A extends B{
static int b = 3;
int b2 = 4;
static
{
System.out.println("子類static變數"+b);
System.out.println("子類靜態程式碼塊");
}
public static void main(String[] args){
System.out.println("main方法被執行");
new A();
}
public A(){
System.out.println("子類構造方法被執行");
}
{
System.out.println("子類非static變數"+b2);
System.out.println("子類構造程式碼塊");
}
}
/*
執行結果:
父類static變數1
父類靜態程式碼塊
子類static變數3
子類靜態程式碼塊
main方法被執行
父類非static變數2
父類構造程式碼塊
父類構造方法被執行
子類非static變數4
子類構造程式碼塊
子類構造方法被執行
*/
若main方法所在類沒有父類,則按規律執行即可
由此,我們還可以總結出類的載入規律: (1)先父類後子類
(2)先靜態後非靜態
(3)先屬性後方法
(4)先聲明後賦值
至此 總結完畢
第一篇部落格,請大神們多多指教,指點一二,再次感謝