1. 程式人生 > >java細節之類中的靜態塊和非靜態塊的執行情況

java細節之類中的靜態塊和非靜態塊的執行情況

這篇文章來源於一道面試題:

public class TestBean extends F{
 
 public TestBean(){
  
  System.out.println("testbean constructor");
 }
 
 
 {System.out.println("testbean");}
 static{System.out.println("testbean static");}

public static void main(String[] args) {
 
  TestBean tb=new TestBean();
  TestBean tb1=new TestBean();
    
 }
 
}
class F{
 public  F(){
  System.out.println("F constructor");
 }
 {System.out.println("F");}
 static{System.out.println("F static");}
 
}
請問執行的輸出結果?結果如下: F static
testbean static
F
F constructor
testbean
testbean constructor
F
F constructor
testbean
testbean constructor
-------------------------------------------------
現在來理一下他們的執行順序:
點選執行之後,從main()入口方法開始執行: TestBean tb=new TestBean();
(一)、要new一個TestBean,肯定得用類載入器先把.class檔案載入到記憶體。
載入類的時候,就會執行類中的靜態塊。 這裡TestBean extends F,所以要依次載入F和TestBean類。於是依次執行F和TestBean中的靜態塊,輸出: F static
testbean static
(二),類載入完後就開始new物件並進行初始化tb。 這裡有個知識點:不要誤解類的初始化物件就只是呼叫建構函式來賦值。 ------------------------類的初始化--------------------------------------------------------------

一共有三種方式對例項變數(物件)進行初始化:

①定義例項變數時指定初始值

②非靜態初始化塊中對例項變數進行初始化,(就是初始化一次就執行非靜態塊一次)

③構造器中對例項變數進行初始化

當new物件 初始化時,①②要先於③執行。而①②的順序則按照它們在原始碼中定義的順序來執行。

同樣,TestBean繼承自F,所以要先初始化F,再初始化TestBean:

所以輸出: F
F constructor
testbean
testbean constructor
-----------------------這裡有個疑惑?---------------------------------- 父類的建構函式,是在子類的建構函式的第一行預設呼叫的,那麼父類的建構函式,應該是在子類的非靜態塊之後執行的啊? 與上面的順序就矛盾了。原因,我還不知道,諸君知道的,不妨留言告訴我一聲。不過執行結果是上面一個結果。那麼反推執行順序,就是如上文所說。 ------------------------------------------------------------------------------ (三),再次new物件並初始化tb1 重複上述順序,輸出: F
F constructor
testbean
testbean constructor
不再執行靜態塊,靜態塊只在類載入時執行一次。