1. 程式人生 > >JAVA學習——靜態程式碼塊、構造程式碼塊、構造器、普通程式碼塊的執行順序

JAVA學習——靜態程式碼塊、構造程式碼塊、構造器、普通程式碼塊的執行順序

概念

在此之前,我們先來看看JAVA中的這些程式碼塊:

  • 靜態程式碼塊

在類中使用static修飾,並使用"{}"括起來的程式碼片段。用於靜態變數的初始化或物件建立前的環境初始化。

  • 構造程式碼塊

在類中沒與任何的字首或字尾,並使用"{}"括起來的程式碼片段。

  • 普通程式碼塊

就是在方法後面使用"{}"括起來的程式碼片段,不能單獨執行,必須用其方法名呼叫才可以執行。

  • 同步程式碼塊

使用synchronize關鍵字修飾,並使用"{}"括起來的程式碼片段。

表示在同一時間只能有一個執行緒進入到該方法塊中,是一種多執行緒保護機制。

例項

程式碼

public class Code {

	// 靜態程式碼塊
	static{
		System.out.println("我是靜態程式碼塊");
	}
	
	{// 構造程式碼塊
		System.out.println("我是構造程式碼塊");
	}

	// 無參構造方法(構造器)(構造器的返回值型別就是類本身,無需寫)
	public Code() {
		System.out.println("我是無參構造方法");
	}
	
	// 普通程式碼塊,必須要有返回值型別
	public void Code1() {
		System.out.println("我是普通程式碼塊");
	}
	
	public static void main(String[] args) {

		Code c1 = new Code();
		Code c2 = new Code();

		c1.Code1();
		c2.Code1();
	}
}

結果

理解了上面的結果之後,問題來了,我們都知道程式碼塊沒有獨立執行的能力, 構造器(構造方法)是通過關鍵詞new來呼叫執行, 普通程式碼塊通過方法名呼叫執行, 那編譯器是如何處理構造程式碼塊的?

實際上,很簡單,編譯器會把構造程式碼塊插入到每個建構函式的最前端。相當於:

// 無參構造方法(構造器)(構造器返回值型別就是類本身,無需寫)
public Code() {
	System.out.println("我是構造程式碼塊");
	System.out.println("我是無參構造方法");
}

這樣,自然在通過new關鍵字生成一個例項的時侯會先執行構造程式碼塊,然後再執行其他程式碼(注意:構造程式碼塊不是在建構函式之前執行,而是依託於建構函式)

這就有了構造程式碼塊的兩個主要應用場景:

1. 初始化例項變數

如果每個建構函式都需要初始化變數,就可以通過構造程式碼塊來實現,從而取代在每個建構函式中都去呼叫初始化例項變數的方法。

2. 初始化例項環境

一個物件必須在適當的場景下才能存在,如果沒有適當的場景,則就需要在建立物件的時候建立此場景。如構造程式碼塊

這兩個場景就是利用了構造程式碼塊的兩個特性:

1. 在每個建構函式中都執行

2. 在建構函式中它會首先執行

構造程式碼塊的出現就是為了提取建構函式的共同量,降低各個建構函式的程式碼重複度。如下:

public class Code {

	public static int count = 0;

	{
		count++;
	}

	public Code() {
	}

	public Code(int i) {
		this();
	}

	public Code(String string) {
	}

	public static void main(String[] args) {
		new Code();
		new Code(1);
		new Code("1");
		System.out.println(Code.count);
	}
}

結果為3

拓展

對於有繼承的類來說,其中順序又是如何的呢?