Java 代碼塊詳解

在程序編程中,可以直接使用“{}”定義一段語句。根據定義的位置以及聲明關鍵字的不同,可以分爲四種:普通代碼塊、構造代碼塊、靜態代碼塊和同步代碼塊。一般來說代碼塊是不能單獨運行的,它必須要有運行主體。

一、普通代碼塊

普通代碼塊是定義在方法之中的代碼塊。我們先觀察一下代碼:

package com.wz.thisdemo;

public class TestDemo {
    public static void main(String args[]) {
        if (true) {
            int x = 10; // 局部變量
            System.out.println("x = " + x);
        }
        int x = 100; // 全局變量
        System.out.println("x = " + x);
    }
}

把if取消,就成了普通代碼塊:

package com.wz.thisdemo;

public class TestDemo {
    public static void main(String args[]) {
        { // 普通代碼塊
            int x = 10; // 局部變量
            System.out.println("x = " + x);
        }
        int x = 100; // 全局變量
        System.out.println("x = " + x);
    }

}

運行結果:

x = 10
x = 100

實際上、普通代碼塊可以防止在方法中編寫代碼過多引起變量重名,從而對一個方法中的代碼進行分割。

二、構造代碼塊

普通代碼塊是定義在方法之中的,而構造代碼塊是定義在類中的代碼塊。

package com.wz.thisdemo;

class Person {
    public Person() {
        System.out.println("構造方法。");
    }

    { // 構造塊
        System.out.println("構造塊。");
    }
}

public class TestDemo {
    public static void main(String args[]) {
        new Person();
        new Person();
        new Person();
    }
}

運行結果:

構造塊。
構造方法。
構造塊。
構造方法。
構造塊。
構造方法。

可以發現,構造塊先於構造方法執行,而且每當有一個新的實例化對象產生的時候,就會出現構造塊的執行

從上面的運行結果可以看出在new一個對象的時候總是先執行構造代碼,再執行構造函數,但是有一點需要注意構造代碼不是在構造函數之前運行的,它是依託構造函數執行的。正是由於構造代碼塊有這幾個特性,所以它常用於如下場景:

(1)初始化實例變量
如果一個類中存在若干個構造函數,這些構造函數都需要對實例變量進行初始化,如果我們直接在構造函數中實例化,必定會產生很多重複代碼,繁瑣和可讀性差。這裏我們可以充分利用構造代碼塊來實現。這是利用編譯器會將構造代碼塊添加到每個構造函數中的特性。

(2)初始化實例環境
一個對象必須在適當的場景下才能存在,如果沒有適當的場景,則就需要在創建對象時創建此場景。我們可以利用構造代碼塊來創建此場景,尤其是該場景的創建過程較爲複雜。構造代碼會在構造函數之前執行。

上面兩個常用場景都充分利用構造代碼塊的特性,能夠很好的解決在實例化對象時構造函數比較難解決的問題,利用構造代碼不僅可以減少代碼量,同時也是程序的可讀性增強了。特別是當一個對象的創建過程比較複雜,需要實現一些複雜邏輯,這個時候如果在構造函數中實現邏輯,這是不推薦的,因爲我們提倡構造函數要儘可能的簡單易懂,所以我們可以使用構造代碼封裝這些邏輯實現部分。

三、靜態代碼塊

靜態塊也是定義在類中的,一個構造塊上使用了static關鍵字進行定義的話,那麼就表示靜態塊,它的主要目的就是對靜態屬性進行初始化。靜態塊要考慮兩種情況:

1、在非主類中使用

package com.wz.thisdemo;

class Person {
    public Person() {
        System.out.println("構造方法。");
    }

    { // 構造塊
        System.out.println("構造塊。");
    }
    static {
        System.out.println("靜態塊。");
    }
}

public class TestDemo {
    public static void main(String args[]) {
        new Person();
        new Person();
        new Person();
    }
}

運行結果:

靜態塊。
構造塊。
構造方法。
構造塊。
構造方法。
構造塊。
構造方法。

可以發現,靜態塊優先於構造塊執行,而且不管有多少個實例化對象產生,靜態塊只調用一次。

2、在主類中定義的靜態塊

package com.wz.thisdemo;

public class TestDemo {
    static {
        System.out.println("靜態塊。");
    }

    public static void main(String args[]) {
        System.out.println("Hello World .");
    }
}

運行結果:

靜態塊。
Hello World .

在主類之中的靜態塊優先於主方法執行。

四、靜態代碼塊、構造代碼塊、構造函數執行順序

靜態代碼塊,靜態,其作用級別爲類,構造代碼塊、構造函數,構造,其作用級別爲對象。

1、 靜態代碼塊,它是隨着類的加載而被執行,只要類被加載了就會執行,而且只會加載一次,主要用於給類進行初始化。

2、 構造代碼塊,每創建一個對象時就會執行一次,且優先於構造函數,主要用於初始化不同對象共性的初始化內容和初始化實例環境。

3、 構造函數,每創建一個對象時就會執行一次。同時構造函數是給特定對象進行初始化,而構造代碼是給所有對象進行初始化,作用區域不同。

通過上面的分析,他們三者的執行順序爲:靜態代碼塊 > 構造代碼塊 > 構造函數。

五、同步代碼塊

使用 synchronized 關鍵字修飾,並使用“{}”括起來的代碼片段,它表示同一時間只能有一個線程進入到該方法塊中,是一種多線程保護機制。
(具體將會在多線程中講到)

參考:

http://www.cnblogs.com/chenssy/p/3413229.html

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