在java中,代碼塊一般可分為普通代碼塊、構造代碼塊、靜態代碼塊、同步代碼塊,這里我們主要將普通代碼塊和初始化代碼塊(構造+靜態代碼塊):
一、普通代碼塊:
普通代碼塊僅出現於方法中,起到分隔不同功能代碼的作用,其運行順序依據代碼塊出現的先后。
public static void main(String[] args) {
System.out.println("hello world");
}
二、初始化代碼塊:
初始化代碼塊分為靜態初始化代碼塊和非靜態初始化代碼塊兩類。
初始化代碼塊出現於類的主體中,在類的聲明中,可以包含多個初始化塊,當創建類的實例時,就會依次執行這些代碼塊。如果使用 static 修飾初始化塊,就稱為靜態初始化塊。
非靜態初始化代碼塊多為構造方法,它隱性運行於創建類的對象時,順序依據代碼塊的先后排列,且這些代碼塊間可以存在其他方法。也就是說在實例化這個對象時,會從類的頭到尾檢索一遍來運行初始化代碼塊。
以下代碼將詳細的說明靜態代碼塊、初始化代碼塊和構造方法三者的執行順序:
public class TestClass5 {
//系統在初始化類時,不僅會初始化該類中的靜態初始化代碼塊,還回上溯到引用的包中的類的靜態初始化代碼塊
static {
//只在類加載時(包括子類)執行一遍
//靜態初始化塊只能給靜態變量賦值,不能初始化普通的成員變量
System.out.print("類加載:");
System.out.print("父類-靜態方法 ");
}
public TestClass5(){
//每次創建(包括子類)對象都會執行
System.out.print("父類-無參構造方法 ");
}
public TestClass5(String str){
//帶參的構造方法在創建對象時,不會自動執行
System.out.print("父類-有參構造方法 ");
}
{
//每次創建(包括子類)對象都會執行
System.out.print("父類-初始化代碼塊 ");
}
}
class ChildTestClass5 extends TestClass5{
static {
//只在類加載時(包括子類)執行一遍
//靜態初始化塊只能給靜態變量賦值,不能初始化普通的成員變量
System.out.println("子類-靜態方法 ");
}
public ChildTestClass5(){
//每次創建(包括子類)對象都會執行
System.out.print("子類-無參構造方法 ");
}
{
//每次創建(包括子類)對象都會執行
System.out.print("子類-初始化代碼塊 ");
}
public static void main(String[] args) {
//創建父類對象時不會去執行子類的構造方法
System.out.print("執行new TestClass5():");
new TestClass5();
System.out.println();
//創建父類對象時,如果帶有參數,則不會去執行無參的構造方法,只執行參數個數及類型對應的構造方法
System.out.print("執行new TestClass5(\"10\"):");
new TestClass5("10");
System.out.println();
//創建子類對象時,會先執行父類的構造方法,然后才會去執行子類的構造方法
System.out.print("執行new ChildTestClass5():");
new ChildTestClass5();
System.out.println();
}
}
執行后打印結果為:
類加載:父類-靜態方法 子類-靜態方法
執行new TestClass5():父類-初始化代碼塊 父類-無參構造方法
執行new TestClass5("10"):父類-初始化代碼塊 父類-有參構造方法
執行new ChildTestClass5():父類-初始化代碼塊 父類-無參構造方法 子類-初始化代碼塊 子類-無參構造方法