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