Java——靜態字段和實例字段的初始化說明

我們都知道,在Java語言中,有靜態字段和實例字段,但是,它們兩者之間的初始化是有區別的。

其中,需要說明的一點就是:靜態字段由類調用,實例字段由對象調用!!!

1. 靜態字段

static 靜態字段 / 靜態變量 的初始化過程,由Java虛擬機JVM加載類後,自動進行靜態字段初始化。

①靜態字段的默認初始化:靜態字段設置爲其類型的默認值。

②靜態字段的聲明初始化:靜態字段設置爲聲明時的初始化值。

③靜態字段的靜態塊初始化:依次調用靜態塊進行初始化。

從源程序的角度看,靜態字段以上三種初始化的順序:

①首先進行默認初始化。

②然後根據聲明初始化、靜態塊初始化這兩者在程序中的順序來依次進行!!!(兩者誰先誰後是不一定的)

2. 實例字段 

實例字段 / 實例變量 的初始化過程,由new進行實例初始化。

①實例字段的默認初始化:實例字段設置爲其類型的默認值。

②實例字段的聲明初始化:實例字段設置爲聲明時的初始化值。

③實例字段的實例構造方法初始化:根據實例構造方法簽名,調用實例構造方法進行初始化。

從源程序的角度看,實例字段以上三種初始化的順序:

①首先必須進行默認初始化。

②然後進行聲明初始化。

③最後進行實例構造方法的初始化。

因爲實例字段相對來說,比較好理解,所以我們在這裏重點對靜態字段的初始化進行講解!!!

我們依次來看下面的五個程序!!!👇👇👇 

Program Ⅰ: (沒有靜態塊,靜態變量的聲明初始化的順序不同)

class Test1 {
	public Test1() {
		System.out.println("Test1實例構造函數之前 a="+Test.a+",b="+Test.b);
		Test.a++;
		Test.b++;
		System.out.println("Test1實例構造函數之後 a="+Test.a+",b="+Test.b);
	}
}
public class Test {
	public static Test1 t=new Test1();
	public static int a;
	public static int b=10;
	public static void main(String[] args) {
		System.out.println("最後的結果:a="+Test.a+",b="+Test.b);
	}
}

Program Output Ⅰ: 

Program Analysis Ⅰ:

按此順序初始化靜態變量:默認初始化→聲明初始化 

默認初始化:靜態變量按照聲明的順序依次設置爲該類型的默認值。

聲明初始化:靜態變量按聲明的順序依次設置爲聲明初始化的值,如果沒有聲明初始化就跳過。 

靜態字段初始化流程如下:

1. 默認初始化:類被加載後,首先靜態字段會進行默認初始化。結果:t=null,a=0,b=0

2. 聲明初始化:①首先進行靜態字段t的聲明初始化,創建Test1的實例,調用實例構造方法,執行之後的結果:a=1,b=1

                          ②然後進行靜態字段a和b的聲明初始化,因爲靜態字段a沒有聲明初始化,所以就跳過,並執行Test.a++,                     此時a=1;但是靜態字段b由聲明初始化,結果b=10。(大家對照這個流程,看一下上面的代碼和運行結果)

 

Program Ⅱ:(沒有靜態塊,靜態變量的聲明初始化的順序不同)

class Test1 {
	public Test1() {
		System.out.println("Test1實例構造函數之前 a="+Test.a+",b="+Test.b);
		Test.a++;
		Test.b++;
		System.out.println("Test1實例構造函數之後 a="+Test.a+",b="+Test.b);
	}
}
public class Test {
	public static int a;
	public static int b=10;
        public static Test1 t=new Test1();
	public static void main(String[] args) {
		System.out.println("最後的結果:a="+Test.a+",b="+Test.b);
	}
}

Program Output Ⅱ: 

Program Analysis Ⅱ:

按此順序初始化靜態變量:默認初始化→聲明初始化 

默認初始化:靜態變量按照聲明的順序依次設置爲該類型的默認值。

聲明初始化:靜態變量按聲明的順序依次設置爲聲明初始化的值,如果沒有聲明初始化就跳過。 

靜態字段初始化流程如下:

1. 默認初始化:類被加載後,首先靜態字段會進行默認初始化。結果:t=null,a=0,b=0。

2. 聲明初始化:①首先進行靜態字段a和b的聲明初始化,因爲靜態字段a沒有聲明初始化,所以就跳過,結果還是a=0;但                     靜態字段b有聲明初始化,所以結果是b=10。

                         ②然後再進行靜態字段t的聲明初始化,創建Test1的實例,調用實例構造方法,Test.a++,Test.b++,執行                     之後的結果是a=1,b=11。(大家對照這個流程,看一下上面的代碼和運行結果)

 

Program Ⅲ:(有靜態塊,靜態塊定義在聲明初始化語句之後)

class Test1 {
	public Test1() {
		System.out.println("Test1實例構造函數之前 a="+Test.a+",b="+Test.b);
		Test.a++;
		Test.b++;
		System.out.println("Test1實例構造函數之後 a="+Test.a+",b="+Test.b);
	}
}
public class Test {
	public static Test1 t=new Test1();
	public static int a;
	public static int b=10;
	static {
		a=20;
		System.out.println("static靜態代碼塊1之後 a="+Test.a+",b="+Test.b);
	}
	static {
		b=30;
		System.out.println("static靜態代碼塊2之後 a="+Test.a+",b="+Test.b);
	}
	public static void main(String[] args) {
		System.out.println("最後的結果:a="+Test.a+",b="+Test.b);
	}
}

Program Output Ⅲ:

Program Analysis Ⅲ:

按此順序初始化靜態變量:默認初始化→聲明初始化→靜態代碼塊初始化

默認初始化:靜態變量按照聲明的順序依次設置爲該類型的默認值。

聲明初始化:靜態變量按聲明的順序依次設置爲聲明初始化的值,如果沒有聲明初始化就跳過。 

靜態代碼塊初始化:按照靜態代碼塊的順序依次設置靜態字段的值。

靜態字段初始化流程如下:

1. 默認初始化:類被加載後,首先靜態字段會進行默認初始化。 結果:t=null,a=0,b=0。

2. 聲明初始化:①首先進行靜態字段t的聲明初始化,創建Test1的實例,調用實力構造方法,執行之後的結果是a=1,b=1

                          ②進行靜態字段a和b的聲明初始化,因爲靜態字段a沒有聲明初始化,所以就跳過,結果還是a=1;但是靜                    態字段b有聲明初始化,所以結果是b=10。

3. 靜態代碼塊初始化:①首先執行靜態代碼塊1,對靜態字段a進行靜態塊初始化,結果是a=20,b=10。

                                     ②然後執行靜態代碼塊2,對靜態字段b進行靜態塊初始化,結果是a=20,b=30。(大家對照這個流程,看一下上面的代碼和運行結果)

 

Program Ⅳ:(有靜態塊,靜態塊定義在聲明初始化語句之前)

class Test1 {
	public Test1() {
		System.out.println("Test1實例構造函數之前 a="+Test.a+",b="+Test.b);
		Test.a++;
		Test.b++;
		System.out.println("Test1實例構造函數之後 a="+Test.a+",b="+Test.b);
	}
}
public class Test {
	static {
		a=20;
		System.out.println("static靜態代碼塊1之後 a="+Test.a+",b="+Test.b);
	}
	static {
		b=30;
		System.out.println("static靜態代碼塊2之後 a="+Test.a+",b="+Test.b);
	}
	public static Test1 t=new Test1();
	public static int a;
	public static int b=10;
	public static void main(String[] args) {
		System.out.println("最後的結果:a="+Test.a+",b="+Test.b);
	}
}

Program Output Ⅳ:

Program Analysis Ⅳ:

按此順序初始化靜態變量:默認初始化→靜態代碼塊初始化→聲明初始化

默認初始化:靜態變量按照聲明的順序依次設置爲該類型的默認值。

靜態代碼塊初始化:按靜態塊的順序依次設置靜態字段的值。 

聲明初始化:靜態變量按聲明的順序依次設置爲聲明初始化的值,如果沒有聲明初始化就跳過。

靜態字段初始化流程如下:

1. 默認初始化:類被加載後,首先靜態字段會進行默認初始化。 結果:t=null,a=0,b=0。

2. 靜態代碼塊初始化:①首先執行靜態代碼塊1,對靜態字段a進行靜態塊初始化,結果是a=20,b=0。

                                     ②然後執行靜態代碼塊2,對靜態字段b進行靜態塊初始化,結果是a=20,b=30。

3. 聲明初始化:①首先進行靜態字段t的聲明初始化,創建Test1的實例,調用實例構造方法,執行後的結果是a=21,b=31

                          ②然後進行靜態字段a和b的聲明初始化,因爲靜態字段a沒有聲明初始化,所以就跳過,結果還是a=21;                      但是靜態字段b有聲明初始化,所以結果是b=10。(大家對照這個流程,看一下上面的代碼和運行結果)

 

Program Ⅴ:(有靜態塊,聲明初始化語句在兩個靜態塊定義之間)

class Test1 {
	public Test1() {
		System.out.println("Test1實例構造函數之前 a="+Test.a+",b="+Test.b);
		Test.a++;
		Test.b++;
		System.out.println("Test1實例構造函數之後 a="+Test.a+",b="+Test.b);
	}
}
public class Test {
	static {
		a=20;
		System.out.println("static靜態代碼塊1之後 a="+Test.a+",b="+Test.b);
	}
	public static Test1 t=new Test1();
	public static int a;
	public static int b=10;
	static {
		b=30;
		System.out.println("static靜態代碼塊2之後 a="+Test.a+",b="+Test.b);
	}
	public static void main(String[] args) {
		System.out.println("最後的結果:a="+Test.a+",b="+Test.b);
	}
}

Program Output Ⅴ:

Program Analysis Ⅴ:

按此順序初始化靜態變量:默認初始化→靜態代碼塊1初始化→聲明初始化→靜態代碼塊2初始化

默認初始化:靜態變量按照聲明的順序依次設置爲該類型的默認值。

靜態代碼塊初始化:按靜態塊的順序依次設置靜態字段的值。 

聲明初始化:靜態變量按聲明的順序依次設置爲聲明初始化的值,如果沒有聲明初始化就跳過。

靜態字段初始化流程如下:

1. 默認初始化:類被加載後,首先靜態字段會進行默認初始化。 結果:t=null,a=0,b=0。

2. 靜態代碼塊1初始化:對靜態字段a進行靜態塊初始化,結果a=20,b=0。

3. 聲明初始化:①首先進行靜態字段t的聲明初始化,創建Test1的實例,調用實例構造方法,執行之後結果是a=21,b=1。

                          ②然後進行靜態字段a和b的聲明初始化,因爲靜態字段a沒有聲明初始化,所以就跳過,結果還是a=21;                      但是靜態字段b有聲明初始化,所以結果是b=10。

4. 靜態代碼塊2初始化:對靜態字段b進行靜態塊初始化,結果a=21,b=30。(大家對照這個流程,看一下上面的代碼和運行結果)


根據上面這五個Java小程序,大家可能覺得比較多,看起來不舒服,但是靜態字段這部分內容還是很重要的!!!

所以希望大家可以耐心的去理解每一個程序代碼,對我們後面的Java知識的學習還是有很大幫助的!!!😊😊😊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章