第十七節:易混淆的概念(靜態和非靜態、拆箱和裝箱)

一. 靜態和非靜態html

1. 概念介紹面試

  ① 靜態類(被static修飾) vs  普通類(沒有被static修飾)數組

  ② 靜態成員:被static修飾的成員,好比:靜態方法、靜態字段等瀏覽器

  ③ 普通成員(實例成員):不被static修飾的成員,好比:普通方法、普通字段緩存

2. 運行機制服務器

  ① 靜態成員在程序運行的時候會「先於」實例成員被加載到內存中,靜態成員不須要單首創建,固然靜態類也不能被實例化。多線程

  好比:靜態字段和靜態構造函數只有在程序第一次使用該類以前被調用,並且只能調用一次,利用該特性,能夠設計單例模式。異步

補充單例模式的代碼:async

 1 public class STwo
 2     {
 3         /// <summary>
 4         /// 模擬耗時的構造函數
 5         /// </summary>
 6         private STwo()
 7         {
 8             long result = 0;
 9             for (int i = 0; i < 1000000; i++)
10             {
11                 result += i;
12             }
13             Thread.Sleep(1000);
14             Console.WriteLine("{0}被構造...", this.GetType().Name);
15         }
16 
17         private static STwo _STwo = null;
18         /// <summary>
19         /// 靜態的構造函數:只能有一個,且是無參數的
20         /// 由CLR保證,只有在程序第一次使用該類以前被調用,並且只能調用一次
21         /// </summary>
22         static STwo()
23         {
24             _STwo = new STwo();
25         }
26 
27         public static STwo CreateIntance()
28         {
29             return _STwo;
30         }
31     }
View Code
 1 public  class SThird
 2     {
 3         /// <summary>
 4         /// 模擬耗時的構造函數
 5         /// </summary>
 6         private SThird()
 7         {
 8             long result = 0;
 9             for (int i = 0; i < 1000000; i++)
10             {
11                 result += i;
12             }
13             Thread.Sleep(1000);
14             Console.WriteLine("{0}被構造...", this.GetType().Name);
15         }
16         /// <summary>
17         /// 靜態變量:由CLR保證,在程序第一次使用該類以前被調用,並且只調用一次
18         /// </summary>
19         private static SThird _SThird = new SThird();
20 
21         public static SThird CreateIntance()
22         {
23             return _SThird;
24         }
25     }
View Code

  ② 實例成員:只有建立了對象(即進行了類的實例化)纔會存在於內存中。ide

  證實:在StaticInstroduceDemo類中的靜態變量a上加斷點(方法體內部加斷點,兩次實例化類的時候加斷點),而後在客戶端實例化兩次 StaticInstroduceDemo類,分別調用ShowStaticInstroduce方法,

  發現:第一次實例化的時候進入靜態變量a上的斷點,而後在調用對應的方法,而第二次實例化的時候再也不進入靜態變量a上的斷點,直接進入調用的方法。從而驗證了:靜態成員優先於實例成員進入內存,且只在第一次使用該類的時候進行初始化分配內存,後續將不在分配.

3. 基於以上運行機制能夠得出如下幾個結論

① 普通類:

  a. 普通類中能夠存在靜態成員(靜態方法、靜態字段),但裏面的靜態方法不能調用普通類中的普通字段<普通類沒有實例化的話,普通字段是不存在的>。

  b. 普通類中普通方法能夠調用裏面的靜態字段<靜態成員先於實例成員加載到內存中>

eg:

② 靜態類:

靜態類中只能存在靜態成員(靜態方法和靜態字段)

4. 調用形式

  ① 靜態成員: 類名.靜態成員名

  ② 實例成員: 實例名.實例成員名

5. 聲明週期

  ① 對於C/S程序:每啓動一次,至關於一次生命週期,關閉程序生命週期結束,屢次打開客戶端程序互不干擾。 

驗證:上述的ShowStaticInstroduce方法,兩次實例化後調用輸出的結果是2,3 。此時我再打開一個客戶端,結果依舊是2,3,這也很好證實了聲明週期的問題。

  ② 對於B/S程序:static修飾的成員存儲在服務器端中,與客戶端關閉與否無關。《詳見HomeController下的TestStatic方法》

驗證:打開不一樣瀏覽器,分別調用TestStatic1方法,發現每點擊一次按鈕,返回值增長1,關閉該瀏覽器,從新點擊,返回值在原基礎上加1. 關閉IIS從新運行,返回值從新計數。證實:在B/S模式下,static修飾的成員存儲在服務器端內存中,與客戶端關閉與否無關。

 

 

6. 使用場景

  ① 對於C/S程序:static修飾的變量能夠看成緩存來使用。

  ② 對於B/S程序:能夠利用static的特性來設計單例模式,或者面向多線程存儲數據,進行資源的共享<PS: 不考慮性能方面問題和一些極端狀況>。

  ③ 做爲工具類,全局資源共享。

二. 拆箱和裝箱

1. 補充兩個概念:

  值類型:int、double、char、bool、decimal、struct、enum

  引用類型:各類class類、string、數組、接口、委託、object

2. 裝箱:

  將值類型→引用類型

3. 拆箱:

  將引用類型→值類型

4. 經典面試題

請問下面代碼涉及到幾回拆箱和裝箱。

分析:

  ① 第一次裝箱發生在 object m2 = m1;

  ② 第一次拆箱發生在 (int)m2 上;

  因此不少人認爲答案是:1次裝箱和1次拆箱,顯然是不對的。

    咱們繼續分析,熟悉 Console.WriteLine原理的知道內部調用string.Concat()方法進行拼接,而Contact有不少重載,F12看源碼可知,

    該案例只能使用 public static String Concat(object arg0, object arg1); 這個重載,

    因此第2次裝箱和第3次裝箱發生在 m1→object 和(int)m2→object上。

  因此最終答案是 1次拆箱和3次裝箱

5.  特別注意:用什麼類型進行裝箱的,拆箱就拆成什麼類型,不然會拋異常,沒法進行類型轉換。

 

 

 PS:若是你對.Net其餘知識感興趣,能夠參考  DotNet進階系列(持續更新)  ASP.NET MVC深刻淺出系列(持續更新) ORM系列之Entity FrameWork詳解(持續更新)    

       那些年咱們一塊兒追逐的多線程(Thread、ThreadPool、委託異步調用、Task/TaskFactory、Parallerl、async和await)

 

 

 

!

  • 做       者 : Yaopengfei(姚鵬飛)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 本人才疏學淺,用郭德綱的話說「我是一個小學生」,若有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲     明2 : 原創博客請在轉載時保留原文連接或在文章開頭加上本人博客地址,如需代碼請留下你的評論,加我QQ:604649488 (備註:評論的博客名)
相關文章
相關標籤/搜索