靜態塊,構造塊 構造函數以及 靜態塊調用構造對象的 執行次序
請看一段這些方法或者塊的執行代碼:
package Test;
public class People {
private String name = "李四";
{
System.out.println("初始化1");
name = "張三";
age = 20;
}
private int age = 30;
static {
System.out.println("靜態初始化1");
System.out.println("王二開始");
People people = new People("王二", 50);
System.out.println(people);
System.out.println("王二結束");
}
{
System.out.println("初始化2");
name = "趙四";
}
static {
System.out.println("靜態初始化2");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public People(String name, int age) {
super();
System.out.println("有參構造器");
this.name = name;
this.age = age;
}
public People() {
super();
System.out.println("無參構造器");
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "People [name=" + name + ", age=" + age + "]";
}
}
package Test;
public class Main {
public static void main(String[] args) {
System.out.println("tom開始");
People tom = new People("tom", 20);
System.out.println(tom);
System.out.println("tom結束");
System.out.println("jouty開始");
People jouty = new People("jouty", 19);
System.out.println(jouty);
System.out.println("jouty結束");
System.out.println("jerry開始");
People jerry = new People("jerry", 19);
System.out.println(jerry);
System.out.println("jerry結束");
}
}
執行結果:
下面的討論,我們除去了main方法裏面的System.out.println();因爲這些是用於我們將其執行過程分開,讓我們便於觀察
最先執行——靜態塊(包含“靜態塊調用構造對象”)
又結果我們可以看到,最先輸出的是“靜態初始化1”,即靜態塊最先執行了,因爲在類的第一次加載的時候,就會進行靜態域的初始化,與實例域一樣,除非顯示的設置爲其他值,否則默認的初始化是0、false或null。他們的執行順序,按照定義語句時的先後順序執行
然後執行——構造塊
在“靜態初始化1”塊裏面,我們還定義了一個對象實例,但是,後續顯示的卻是“初始化1”、“初始化2”、“有參構造器”等,直到該name = “王二”;的實例結束; 因爲執行是先執行初始化塊的,但是靜態塊又比構造快早,之所以出現“初始化1”、“初始化2”是因爲,第一個靜態塊即“靜態初始化1”還沒有執行好,所以,後面的靜態塊都不會執行,所以執行了每一次實例化對象都會執行的構造快,直到構造塊結束後,就相當於第一個靜態塊加載結束了,這個時候纔開始加載下一個靜態塊
最後執行——構造函數
當所有的靜態塊都加載結束,纔開始執行類對象的初始化,即第一個 People Tom = new People(“Tom”,20);而構造塊則又是在構造函數執行之前,靜態塊之後,且構造塊是伴隨着每一次類對象實例化都會執行的,所以這個Tom的時候,是先執行了“初始化1”、“初始化2”接着纔是有參構造函數(有參構造器);
後面的jouty和jerry都是一樣的,因爲靜態塊只有在類加載的時候執行,且執行一次,所以後面不會再輸出“靜態初始化1”、“靜態初始化2”,而只會執行構造塊“初始化1”、“初始化2”,且是在“有參構造器(或者無參構造起)”之前