編譯器在編譯的時候,會事先分析所需要的靜態字段,如果這些靜態字段所在的類有靜態的建構函式,則忽略靜態欄位的初始化,否則先進行靜態欄位的初始化。對類的靜態成員初始化的順序取決於在main函式中的引用順序,先引用到的先進行初始化,但如果類的靜態成員的初始化依賴於其它類的靜態成員,則會先初始化被依賴類的靜態成員。而帶有靜態建構函式的類的靜態字段,只有在引用到的時候才進行初始化。
接下來,用例項來對以上的一段總結性的描述逐句分析:
1、編譯器在編譯的時候,會事先分析所需要的靜態字段,如果這些靜態字段所在的類有靜態的建構函式,則忽略靜態欄位的初始化,否則先進行靜態欄位的初始化。
==無靜態建構函式:上圖中例項的執行流程就是紅色數字標記的順序,首先,在編譯器進行編譯時,發現main主函式中會用到a類的靜態欄位x,所以,會在程式開始執行之前去對能用到的靜態字段進行初始化(在無靜態建構函式的前提下);b類中的靜態字段沒有初始化的原因是編譯時沒有發現用到此靜態字段;靜態欄位在il中標記為beforefliedinit;
將上圖中的普通建構函式換為靜態建構函式會是什麼效果呢?
==靜態建構函式:當類a中有靜態的建構函式時,其靜態字段不再提前去初始化,而是當呼叫時才進行初始化;當執行完靜態欄位後,會緊接著去執行靜態建構函式中的**塊;值得一說的是,如果a類中有乙個靜態的方法,當main函式呼叫時則先執行a類的靜態建構函式,再去執行靜態方法;
2、對類的靜態成員初始化的順序取決於在main函式中的引用順序,先引用到的先進行初始化(這個就不用寫例子了,對於兩個相同狀態的類(都含有靜態建構函式或都沒有),其中類靜態欄位的初始化的順序都是按照其在main函式中呼叫時的順序執行的),當然如果過乙個有靜態建構函式,另乙個沒有靜態的建構函式的話,那就另當別論了!
3、如果類的靜態成員的初始化依賴於其它類的靜態成員,則會先初始化被依賴類的靜態成員。
==首先,上圖的**中a類和b類都含有普通的建構函式,並且主程式中都用到了這兩個類中的靜態字段,那麼它們的靜態欄位就會在主程式執行之前進行初始化,然後當有多個靜態欄位時,他們的執行順序就是按照主程式中呼叫的順序來執行!如上圖:先初始化y,再初始化x
4、如果類的靜態成員的初始化依賴於其它類的靜態成員,則會先初始化被依賴類的靜態成員
==如上圖,在編譯器編譯時,檢測到會用到a類的靜態字段,那麼就會在main主函式執行之前對a類的x欄位進行初始化,但是x欄位中又用到了b類的y欄位,所以就會先初始化b類中的y欄位,再初始化a類的x欄位!也就是先初始化被依賴的靜態字段。
5、而帶有靜態建構函式的類的靜態字段,只有在引用到的時候才進行初始化。
這裡才是部落格中主要的,靜態建構函式的作用就是不讓靜態欄位在主程式執行之前進行初始化,而是當主程式呼叫它時才執行,並且緊接著執行該字段索在類的靜態建構函式中的**
==上例中
因為a類和b類都含有靜態的建構函式,所有就避免了其類中靜態欄位的提前初始化,當呼叫用時才執行,並且在上例中a類的x欄位又依賴b類的y欄位(因為都是普通的建構函式,所以不會提前執行,而是用到時才執行),所以當程式到達a的x欄位時就會去呼叫b類的y欄位(緊接著執行b類的靜態建構函式),回來之後再繼續執行a類的靜態夠走啊函式!
這個部落格中寫得也非常的詳細:部落格位址**
2013-9-22更新
==當第一次呼叫靜態欄位時,就會執行所有靜態字段,並執行靜態建構函式,下次再呼叫其他靜態欄位時,就直接取即可,不必在執行一遍user類
==只要使用此類,例如例項化,就會執行類中的靜態字段。
由單例模式學到 volatile關鍵字
msdn上說 volatile 關鍵字指示乙個字段可以由多個同時執行的執行緒修改。宣告為 volatile 的字段不受編譯器優化的限制。這樣可以確保該字段在任何時間呈現的都是最新的值。volatile 關鍵字可應用於以下型別的字段 可變關鍵字僅可應用於類或結構字段。不能將區域性變數宣告為 volat...
單例模式和靜態類的區別
1.首先明確一下,靜態成員並不是什麼程式載入時建立並初始化的,而是類載入時進行。類的載入是第一次真正用到它的時候 拿類new例項或呼叫它的靜態方法 進行的,而這個載入過程需要將 class 檔案中構成類的靜態和例項方法等類的成員的位元組碼指令一同載入到記憶體中,而後要為靜態域分配儲存空間並使用靜態塊...
靜態建構函式和靜態類
靜態建構函式的幾點注意 一.乙個類只能定義乙個靜態建構函式。換句話說,靜態建構函式不能被過載。二.靜態建構函式不允許訪問修飾符並且不能接受任何引數。三.無論建立了多少型別的物件,靜態建構函式只執行一次。四.執行庫建立類例項或呼叫者首次訪問靜態成員之前,執行庫會呼叫靜態建構函式。五.靜態建構函式的執行...