靜態代碼塊:用staitc聲明,jvm加載類時執行,僅執行一次
構造代碼塊:類中直接用{}定義,每一次創建對象時執行。
執行順序優先級:靜態塊,main(),構造塊,構造方法。
public HelloA(){//構造函數
}
關於構造函數,以下幾點要注意:
1.對象一建立,就會調用與之相應的構造函數,也就是說,不建立對象,構造函數時不會運行的。
2.構造函數的作用是用於給對象進行初始化。
3.一個對象建立,構造函數只運行一次,而一般方法可以被該對象調用多次。
{//構造代碼塊
}
關於構造代碼塊,以下幾點要注意:
static {//靜態代碼塊
}
關於靜態代碼塊,要注意的是:
public class Test{
staitc int cnt=6;
static{
cnt+=9;
}
public static void main(String[] args) {
System.out.println(cnt);
}
static{
cnt/=3;
}
}
運行結果:
5
例子1:
public class HelloA {
public HelloA(){//構造函數
System.out.println("A的構造函數");
}
{//構造代碼塊
System.out.println("A的構造代碼塊");
}
static {//靜態代碼塊
System.out.println("A的靜態代碼塊");
}
public static void main(String[] args) {
}
}
運行結果:
A的靜態代碼塊
例子2:
public class HelloA {
public HelloA(){//構造函數
System.out.println("A的構造函數");
}
{//構造代碼塊
System.out.println("A的構造代碼塊");
}
static {//靜態代碼塊
System.out.println("A的靜態代碼塊");
}
public static void main(String[] args) {
HelloA a=new HelloA();
}
}
運行結果:
A的靜態代碼塊
A的構造代碼塊
A的構造函數
例子3:
public class HelloA {
public HelloA(){//構造函數
System.out.println("A的構造函數");
}
{//構造代碼塊
System.out.println("A的構造代碼塊");
}
static {//靜態代碼塊
System.out.println("A的靜態代碼塊");
}
public static void main(String[] args) {
HelloA a=new HelloA();
HelloA b=new HelloA();
}
}
運行結果:
A的靜態代碼塊
A的構造代碼塊
A的構造函數
A的構造代碼塊
A的構造函數
對於一個類而言,按照如下順序執行:
對於靜態變量、靜態初始化塊、變量、初始化塊、構造器,它們的初始化順序依次是(靜態變量、靜態初始化塊)>(變量、初始化塊)>構造器。
例子4:
1 public class InitialOrderTest {
2 /* 靜態變量 */
3 public static String staticField = "靜態變量";
4 /* 變量 */
5 public String field = "變量";
6 /* 靜態初始化塊 */
7 static {
8 System.out.println( staticField );
9 System.out.println( "靜態初始化塊" );
10 }
11 /* 初始化塊 */
12 {
13 System.out.println( field );
14 System.out.println( "初始化塊" );
15 }
16 /* 構造器 */
17 public InitialOrderTest()
18 {
19 System.out.println( "構造器" );
20 }
21
22
23 public static void main( String[] args )
24 {
25 new InitialOrderTest();
26 }
27 }
運行以上代碼,我們會得到如下的輸出結果:
例子5:
public class HelloA {
public HelloA(){//構造函數
System.out.println("A的構造函數");
}
{//構造代碼塊
System.out.println("A的構造代碼塊");
}
static {//靜態代碼塊
System.out.println("A的靜態代碼塊");
}
}
public class HelloB extends HelloA{
public HelloB(){//構造函數
System.out.println("B的構造函數");
}
{//構造代碼塊
System.out.println("B的構造代碼塊");
}
static {//靜態代碼塊
System.out.println("B的靜態代碼塊");
}
public static void main(String[] args) {
HelloB b=new HelloB();
}
}
運行結果:
A的靜態代碼塊
B的靜態代碼塊
A的構造代碼塊
A的構造函數
B的構造代碼塊
B的構造函數
當涉及到繼承時,按照如下順序執行:
例子6:
1 class Parent {
2 /* 靜態變量 */
3 public static String p_StaticField = "父類--靜態變量";
4 /* 變量 */
5 public String p_Field = "父類--變量";
6 protected int i = 9;
7 protected int j = 0;
8 /* 靜態初始化塊 */
9 static {
10 System.out.println( p_StaticField );
11 System.out.println( "父類--靜態初始化塊" );
12 }
13 /* 初始化塊 */
14 {
15 System.out.println( p_Field );
16 System.out.println( "父類--初始化塊" );
17 }
18 /* 構造器 */
19 public Parent()
20 {
21 System.out.println( "父類--構造器" );
22 System.out.println( "i=" + i + ", j=" + j );
23 j = 20;
24 }
25 }
26
27 public class SubClass extends Parent {
28 /* 靜態變量 */
29 public static String s_StaticField = "子類--靜態變量";
30 /* 變量 */
31 public String s_Field = "子類--變量";
32 /* 靜態初始化塊 */
33 static {
34 System.out.println( s_StaticField );
35 System.out.println( "子類--靜態初始化塊" );
36 }
37 /* 初始化塊 */
38 {
39 System.out.println( s_Field );
40 System.out.println( "子類--初始化塊" );
41 }
42 /* 構造器 */
43 public SubClass()
44 {
45 System.out.println( "子類--構造器" );
46 System.out.println( "i=" + i + ",j=" + j );
47 }
48
49
50 /* 程序入口 */
51 public static void main( String[] args )
52 {
53 System.out.println( "子類main方法" );
54 new SubClass();
55 }
56 }
結果:
父類--靜態變量
父類--靜態初始化塊
子類--靜態變量
子類--靜態初始化塊
子類main方法
父類--變量
父類--初始化塊
父類--構造器
i=9, j=0
子類--變量
子類--初始化塊
子類--構造器
i=9,j=20
子類的靜態變量和靜態初始化塊的初始化是在父類的變量、初始化塊和構造器初始化之前就完成了。靜態變量、靜態初始化塊,變量、初始化塊初始化了順序取決於它們在類中出現的先後順序。
(1)訪問SubClass.main(),(這是一個static方法),於是裝載器就會為你尋找已經編譯的SubClass類的代碼(也就是SubClass.class文件)。在裝載的過程中,裝載器注意到它有一個基類(也就是extends所要表示的意思),於是它再裝載基類。不管你創不創建基類對象,這個過程總會發生。如果基類還有基類,那麼第二個基類也會被裝載,依此類推。
(2)執行根基類的static初始化,然後是下一個派生類的static初始化,依此類推。這個順序非常重要,因為派生類的“static初始化”有可能要依賴基類成員的正確初始化。
(3)當所有必要的類都已經裝載結束,開始執行main()方法體,並用new SubClass()創建對象。
(4)類SubClass存在父類,則調用父類的構造函數,你可以使用super來指定調用哪個構造函數。基類的構造過程以及構造順序,同派生類的相同。首先基類中各個變量按照字面順序進行初始化,然後執行基類的構造函數的其余部分。
(5)對子類成員數據按照它們聲明的順序初始化,執行子類構造函數的其余部分。
參考文章鏈接:
java-靜態代碼塊,構造代碼塊,構造函數
Java類初始化順序