在Java中代碼塊指的是使用」{}」括起來的代碼稱爲代碼塊。代碼塊一共分爲4種:局部代碼塊,靜態代碼塊,同步代碼塊,構造代碼塊。html
局部代碼塊就是定義在方法體內部的代碼塊。多線程
public class CodeBlockTest { public static void main(String[] args) { int i; { i=10; System.out.println("局部代碼塊"+i); int j=20; System.out.println("局部代碼塊"+j); } System.out.println(i); //Cannot resolve symbol 'j' //System.out.println(j); } }
能夠看到,在局部代碼塊中聲明的變量,只能在局部代碼塊中進行訪問。局部代碼塊能夠操做非局部代碼塊的變量,可是非局部代碼塊不能訪問局部代碼塊的變量。這就起到了很好的分隔,就能夠用來限制局部變量的生命週期,及早釋放,提升內存利用率。若是有多個局部代碼塊,則按照它們定義的前後順序執行。函數
靜態代碼塊就是在類中用static關鍵字修飾的代碼塊,它不能出如今方法體或者代碼塊內,我在上一篇的Static關鍵字中也記錄了靜態代碼塊的使用,因此就把那裏的例子引用過來了。spa
被static修飾的代碼塊也叫靜態代碼塊,會隨着JVM加載類的時候而加載這些靜態代碼塊,而且會自動執行。它們能夠有多個,能夠存放在於該類的任何地方(不能放在方法內部)。JVM會按照它們的前後順序依次執行它們,並且每一個靜態代碼塊只會被初始化一次,不會進行屢次初始化。線程
簡單示例:3d
public class Person{ static { System.out.println("Person類靜態塊"); } public Person() { System.out.println("Person類構造器"); } public static void main(String[] args) { new Son(); System.out.println("-------"); new Son(); } } class Son extends Person{ static { System.out.println("Son類靜態塊"); } public Son() { System.out.println("Son類構造器"); } }
運行結果:code
從運行結果分析:首先運行main()方法,而後JVM就會加載類,由於Son類繼承了Person類,因此會先加載父類Person類,再去加載子類Son。因爲靜態代碼塊會隨着類的加載而加載,因此先輸出父類中靜態代碼塊內容"Person類靜態塊",而後輸出子類中靜態代碼塊內容"Son類靜態塊"。加載完類以後執行main()方法內容,先new了第一個Son實例,因爲子類構造器中默認調用了super(),因此先輸出父類構造器的內容,再輸出子類構造器的內容。以後又new了第二個Son實例,倒是輸出的構造器的內容,說明static靜態塊只加載了一次。結論:靜態代碼塊是先加載父類的靜態代碼塊,而後再加載子類靜態代碼塊,是隨着類的加載而加載,並且只會加載一次。htm
補充:由於入口main()是個方法,也須要用類去調用,因此類的加載優先級>main()方法。對象
是使用synchronized關鍵字修飾的普通代碼塊(其只能用在方法內部)。其做用在多線程的環境下,對共享數據進行加鎖, 從而實現線程同步,是一種多線程保護機制。blog
public void show(){ synchronized (obj){ System.out.println("同步代碼塊"); } }
直接在類中用"{}"定義且不加任何關鍵字的代碼塊成爲構造代碼塊。
public class CodeBlockTest { { System.out.println("構造代碼塊..."); } public CodeBlockTest() { System.out.println("無參構造器..."); } public static void main(String[] args) { new CodeBlockTest(); new CodeBlockTest(); } }
運行結果:
從運行結果容易看出,在建立對象時,構造代碼塊纔會被執行,並且優先於構造方法執行(這裏和構造塊寫前寫後不要緊,將構造塊寫在構造方法後面也是同樣的結果)。並且每當有對象被建立的時,都會執行構造代碼塊。若是存在多個構造代碼塊,則執行順序按照定義順序依次執行。
構造代碼塊的做用:能夠用來初始化實例變量和實例環境(即建立對象的必要條件),這樣不只能夠減小代碼量,同時也能夠加強程序的可讀性。
注意:構造代碼塊並非真正的在構造方法以前執行的,JVM在編譯的時候會把構造代碼塊插入到每一個構造函數的最前面,構造代碼塊隨着構造方法的執行而執行,若是某個構造方法調用了其餘的構造方法,那麼構造代碼塊不會插入到該構造方法中以避免構造代碼塊執行屢次。咱們能夠從編譯生成的class文件能夠看出來。
上面講述了四種代碼塊的基本信息,而後咱們來看一下四種代碼塊的執行順序。
public class CodeBlockTest { static { System.out.println("靜態代碼塊..."); } { System.out.println("構造代碼塊..."); } public CodeBlockTest() { System.out.println("無參構造器..."); } public void show(){ { System.out.println("局部代碼塊..."); } } public static void main(String[] args) { System.out.println("main()方法運行"); new CodeBlockTest().show(); System.out.println("----------"); new CodeBlockTest().show(); } }
打印結果:
執行順序(優先級從高到低):靜態代碼塊>mian()方法>構造代碼塊>構造方法>局部代碼塊。其中靜態代碼塊只執行一次。構造代碼塊和局部代碼塊再每次建立對象是都會執行。