【转】静态类与非静态类
靜態(tài)類
繼承(多態(tài))、靜態(tài)本身就是相反的。另外需要知道屬性、事件其實(shí)是些特殊的方法。
使用 static 修飾符聲明屬于類型本身而不是屬于特定對(duì)象的靜態(tài)成員。 static 修飾符可用于類、字段、方法、屬性、運(yùn)算符、事件和構(gòu)造函數(shù),但不能用于索引器、析構(gòu)函數(shù)或類以外的類型。
靜態(tài)類與非靜態(tài)類基本相同,但存在一個(gè)區(qū)別:靜態(tài)類不能實(shí)例化。 也就是說,不能使用 new 關(guān)鍵字創(chuàng)建靜態(tài)類類型的變量。 因?yàn)闆]有實(shí)例變量,所以要使用類名本身訪問靜態(tài)類的成員
對(duì)于 只對(duì)輸入?yún)?shù)進(jìn)行運(yùn)算 而不獲取或設(shè)置 任何內(nèi)部實(shí)例字段的方法集,靜態(tài)類可以方便地用作這些方法集的容器。 例如,在 .NET Framework 類庫中,靜態(tài)類 System.Math 包含的方法只執(zhí)行數(shù)學(xué)運(yùn)算,而無需存儲(chǔ)或檢索特定 Math 類實(shí)例特有的數(shù)據(jù)。 就是說,通過指定類名稱和方法名稱來應(yīng)用類成員。
和所有類類型一樣,當(dāng)加載引用靜態(tài)類的程序時(shí),.NET Framework 公共語言運(yùn)行時(shí) (CLR) 將加載該靜態(tài)類的類型信息。程序不能指定加載靜態(tài)類的確切時(shí)間。 但是,可以保證在程序中首次引用該類前加載該類,并初始化該類的字段并調(diào)用其靜態(tài)構(gòu)造函數(shù)。 靜態(tài)構(gòu)造函數(shù)僅調(diào)用一次,在程序駐留的應(yīng)用程序域的生存期內(nèi),靜態(tài)類一直保留在內(nèi)存中。
下表介紹靜態(tài)類的主要特性:
- 僅包含靜態(tài)成員。
- 無法實(shí)例化。
- 是密封的。
- 不能包含實(shí)例構(gòu)造函數(shù)。
因此,創(chuàng)建靜態(tài)類與創(chuàng)建僅包含靜態(tài)成員和私有構(gòu)造函數(shù)的類基本相同。 私有構(gòu)造函數(shù)阻止類被實(shí)例化。使用靜態(tài)類的優(yōu)點(diǎn)在于,編譯器能夠執(zhí)行檢查以確保不致偶然地添加實(shí)例成員。編譯器將保證不會(huì)創(chuàng)建此類的實(shí)例。
靜態(tài)類是密封的,因此不可被繼承。 它們不能從除 Object 外的任何類中繼承。 靜態(tài)類不能包含實(shí)例構(gòu)造函數(shù),但可以包含靜態(tài)構(gòu)造函數(shù)。 如果非靜態(tài)類包含需要進(jìn)行重要的初始化的靜態(tài)成員,也應(yīng)定義靜態(tài)構(gòu)造函數(shù)。
靜態(tài)類構(gòu)造函數(shù)
靜態(tài)構(gòu)造函數(shù)用于初始化任何 靜態(tài) 數(shù)據(jù),或用于執(zhí)行僅需執(zhí)行一次的特定操作。 在創(chuàng)建第一個(gè)實(shí)例或引用任何靜態(tài)成員之前,將自動(dòng)調(diào)用靜態(tài)構(gòu)造函數(shù)。
例如:
class SimpleClass
{?? static readonly long baseline;
??? static SimpleClass()
??? { baseline = DateTime.Now.Ticks; }
}
靜態(tài)構(gòu)造函數(shù)具有以下特點(diǎn):
- 靜態(tài)構(gòu)造函數(shù)既沒有訪問修飾符,也沒有參數(shù)。
- 在創(chuàng)建第一個(gè)實(shí)例或引用任何靜態(tài)成員之前,將自動(dòng)調(diào)用靜態(tài)構(gòu)造函數(shù)來初始化類。
- 無法直接調(diào)用靜態(tài)構(gòu)造函數(shù)。
- 在程序中,用戶無法控制何時(shí)執(zhí)行靜態(tài)構(gòu)造函數(shù)。
- 靜態(tài)構(gòu)造函數(shù)的典型用途是:當(dāng)類使用日志文件時(shí),將使用這種構(gòu)造函數(shù)向日志文件中寫入項(xiàng)。
- 靜態(tài)構(gòu)造函數(shù)在為非托管代碼創(chuàng)建包裝類時(shí)也很有用,此時(shí)該構(gòu)造函數(shù)可以調(diào)用 LoadLibrary 方法。
- 如果靜態(tài)構(gòu)造函數(shù)引發(fā)異常,運(yùn)行時(shí)將不會(huì)再次調(diào)用該構(gòu)造函數(shù),并且在程序運(yùn)行所在的應(yīng)用程序域的生存期內(nèi),類型將保持未初始化。
靜態(tài)成員
非靜態(tài)類可以包含靜態(tài)的方法、字段、屬性或事件。 即使沒有創(chuàng)建類的實(shí)例,也可以調(diào)用該類中的靜態(tài)成員。 始終通過類名而不是實(shí)例名稱訪問靜態(tài)成員。 無論對(duì)一個(gè)類創(chuàng)建多少個(gè)實(shí)例,它的靜態(tài)成員都只有一個(gè)副本。 靜態(tài)方法和屬性不能訪問其包含類型中的非靜態(tài)字段和事件,并且不能訪問任何對(duì)象的實(shí)例變量(除非在方法參數(shù)中顯式傳遞)。
更常見的做法是聲明具有一些靜態(tài)成員的非靜態(tài)類,而不是將整個(gè)類聲明為靜態(tài)類。 靜態(tài)字段有兩個(gè)常見的用法:一是記錄已實(shí)例化對(duì)象的個(gè)數(shù),二是存儲(chǔ)必須在所有實(shí)例之間共享的值。
靜態(tài)方法可以被重載但不能被重寫,因?yàn)樗鼈儗儆陬?#xff0c;不屬于類的任何實(shí)例。
雖然字段不能聲明為 static const,但 const 字段的行為在本質(zhì)上是靜態(tài)的。 這樣的字段屬于類型,不屬于類型的實(shí)例。
C# 不支持靜態(tài)局部變量(在方法范圍內(nèi)聲明的變量)。
通過在成員的返回類型之前使用 static 關(guān)鍵字可以聲明靜態(tài)類成員,也就是在方法的返回類型前加static。
靜態(tài)成員在第一次被訪問之前并且在調(diào)用靜態(tài)構(gòu)造函數(shù)(如有存在)之前進(jìn)行初始化。 若要訪問靜態(tài)類成員,應(yīng)使用類名而不是變量名來指定該成員的位置。
自問自答,自娛自樂
靜態(tài)成員與實(shí)例成員的性能對(duì)比和生成調(diào)用指令的差別有哪些?
對(duì)靜態(tài)方法的調(diào)用以 Microsoft 中間語言 (MSIL) 生成調(diào)用指令,而對(duì)實(shí)例方法的調(diào)用生成 callvirt 指令,該指令還檢查 null 對(duì)象引用。 但是,兩者之間的性能差異在大多數(shù)時(shí)候并不明顯。
為什么靜態(tài)類不能被繼承?
經(jīng)反編譯查看,Static內(nèi)部是用sealed和abstract兩個(gè)關(guān)鍵字組合實(shí)現(xiàn)的,也就是說沒有static這個(gè)關(guān)鍵字,只是為了方便區(qū)別。
靜態(tài)類的使用和實(shí)例類中靜態(tài)成員的使用技巧?
對(duì)于 只對(duì)輸入?yún)?shù)進(jìn)行運(yùn)算 而不獲取或設(shè)置 任何內(nèi)部實(shí)例字段的方法集,靜態(tài)類可以方便地用作這些方法集的容器。也就是說,這個(gè)類只是一個(gè)工具類,里面都是些方法。
常見的做法是聲明具有一些靜態(tài)成員的非靜態(tài)類,而不是將整個(gè)類聲明為靜態(tài)類。由于無論對(duì)一個(gè)類創(chuàng)建多少個(gè)實(shí)例,它的靜態(tài)成員都只有一個(gè)副本,所以靜態(tài)字段有兩個(gè)常見的用法:一是記錄已實(shí)例化對(duì)象的個(gè)數(shù),二是存儲(chǔ)必須在所有實(shí)例之間共享的值。
靜態(tài)類和非靜態(tài)類之間的包含關(guān)系?
非靜態(tài)類可以包含靜態(tài)類成員,靜態(tài)類只能包含靜態(tài)成員。如下所示:
Static class staticclass{//只能是靜態(tài)成員};
Class newClass{//可以包含靜態(tài)成員};
盡管類的實(shí)例包含該類所有實(shí)例字段的單獨(dú)副本,但每個(gè)靜態(tài)字段只有一個(gè)副本。
?靜態(tài)類成員聲明字段的特殊性:
class Test
{? static int x = y;
?? static int y = 5;
?? static void Main() {
????? Console.WriteLine(Test.x);
????? Console.WriteLine(Test.y);
????? Test.x = 99;
????? Console.WriteLine(Test.x);}
}/*Output: 0 ?5 ?99? */
什么情況下需要在一個(gè)普通類中編寫一個(gè)靜態(tài)成員,而這個(gè)類不能標(biāo)記static?
當(dāng)這個(gè)需要被實(shí)例化的時(shí)候,如果這個(gè)類中有一個(gè)成員是所有對(duì)象都共享的數(shù)據(jù),這時(shí)可以將該類中的這個(gè)成員標(biāo)記為靜態(tài)的,但是這個(gè)類還是一個(gè)實(shí)例類。
特別需要注意的有哪些呢? ??
總結(jié)
以上是生活随笔為你收集整理的【转】静态类与非静态类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】多线程之有状态对象和无状态对象
- 下一篇: 最高可省720元!苏宁易购618大额消费