java中靜態變量,靜態代碼塊,靜態方法,實例變量,匿名代碼塊等的加載順序


轉自:http://blog.csdn.net/mrzhoug/article/details/51581994

一.在Java中,使用”{}”括起來的代碼稱為代碼塊,代碼塊可以分為以下四種: 

1.普通代碼塊:就是類中方法的方法體 
  public void xxx(){ 
      //code 
  } 


2.構造塊:用{}裹起來的代碼片段,構造塊在創建對象時會被調用,每次創建對象時都會被調用,並且優先於類構造函數執行。 構造塊中定義的變量是局部變量。
  { 
     //code 
  } 


3.靜態塊:用static{}裹起來的代碼片段,只會被執行一次(第一次加載此類時執行,比如說用Class.forName("")加載類時就會執行static  block),靜態塊優先於構造塊執行。 
  static{  
     //code 
  } 

4.同步代碼塊:使用synchronized(obj){}裹起來的代碼塊,在多線程環境下,對共享數據進行讀寫操作是需要互斥進行的,否則會導致數據的不一致性。常見的是synchronized用來修飾方法,其語義是任何線程進入synchronized需要先取得對象鎖如果被占用了,則阻塞,實現了互斥訪問共享資源。而synchronized也是有代價的。一個常見的場景是,一個冗長的方法中,其實只有一小段代碼需要訪問共享資源,這時使用同步塊,就只將這小段代碼裹在synchronized  block,既能夠實現同步訪問,也能夠減少同步引入的開銷。 同步代碼塊須寫在方法中。
    synchronized(obj){ 
        //code 

    } 

 

 

 

public class test { //1.第一步,准備加載類 public static void main(String[] args) { new test(); //4.第四步,new一個類,但在new之前要處理匿名代碼塊 } static int num = 4; //2.第二步,靜態變量和靜態代碼塊的加載順序由編寫先后決定 { num += 3; System.out.println("b"); //5.第五步,按照順序加載匿名代碼塊,代碼塊中有打印 } int a = 5; //6.第六步,按照順序加載變量 { // 成員變量第三個 System.out.println("c"); //7.第七步,按照順序打印c } test() { // 類的構造函數,第四個加載 System.out.println("d"); //8.第八步,最后加載構造函數,完成對象的建立 } static { // 3.第三步,靜態塊,然后執行靜態代碼塊,因為有輸出,故打印a System.out.println("a"); } static void run() // 靜態方法,調用的時候才加載// 注意看,e沒有加載 { System.out.println("e"); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

一般順序:靜態塊(靜態變量)——>成員變量——>構造方法——>靜態方法 
1、靜態代碼塊(只加載一次) 2、構造方法(創建一個實例就加載一次)3、靜態方法需要調用才會執行,所以最后結果沒有e 
這里寫圖片描述

這里寫圖片描述

 public class Print { public Print(String s){ System.out.print(s + " "); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
 public class Parent{ public static Print obj1 = new Print("1"); public Print obj2 = new Print("2"); public static Print obj3 = new Print("3"); static{ new Print("4"); } public static Print obj4 = new Print("5"); public Print obj5 = new Print("6"); public Parent(){ new Print("7"); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
 public class Child extends Parent{ static{ new Print("a"); } public static Print obj1 = new Print("b"); public Print obj2 = new Print("c"); public Child (){ new Print("d"); } public static Print obj3 = new Print("e"); public Print obj4 = new Print("f"); public static void main(String [] args){ Parent obj1 = new Child (); Parent obj2 = new Child (); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
執行main方法,程序輸出順序為: 1 3 4 5 a b e 2 6 7 c f d 2 6 7 c f d 
  • 1
  • 1

輸出結果表明,程序的執行順序為: 
如果類還沒有被加載: 
1、先執行父類的靜態代碼塊和靜態變量初始化,並且靜態代碼塊和靜態變量的執行順序只跟代碼中出現的順序有關。 
2、執行子類的靜態代碼塊和靜態變量初始化。 
3、執行父類的實例變量初始化 
4、執行父類的構造函數 
5、執行子類的實例變量初始化 
6、執行子類的構造函數 

如果類已經被加載: 
則靜態代碼塊和靜態變量就不用重復執行,再創建類對象時,只執行與實例相關的變量初始化和構造方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM