文章目錄ide
1.靜態成員、實例成員函數
2.靜態類spa
3.類的靜態成員和非靜態成員區別3d
--------------------------------------分割線---------------------------------------------code
1.1定義及說明對象
數據成員:blog
靜態成員:靜態成員變量是和類相關聯的,能夠做爲類中"共"有的變量(是一個共性的表現),他不依賴特定對象的存在,訪問的時候經過類名加點操做符加變量名來訪問.繼承
實例成員:實例成員變量是和對象相關聯的,訪問實例成員變量依賴於實例的存在.內存
函數成員:
靜態方法:靜態方法是不屬於特定對象的方法,靜態方法能夠訪問靜態成員變量和靜態方法;靜態方法不能夠直接訪問實例變量和實例方法,能夠間接調用,首先要建立一個類的實例,而後經過這一特定對象來調用靜態方法;作用域
實例方法:一個實例方法的執行與特定對象關聯,他的執行須要一個對象存在。實例方法能夠直接訪問靜態變量和實例變量,當多個實例對象存在時,內存中並非存在美個特定的實例方法的拷貝,而是,相同類的全部對象都共享每一個實例方法的一個拷貝(實例方法只佔用「一套」空間)。
靜態成員變量 | 靜態方法 | 實例成員變量 | 實例方法 | |
靜態方法 | 直接訪問 | 直接訪問 | 不可直接訪問 | 不可直接訪問 |
實例方法 | 直接訪問 | 直接訪問 | 直接訪問 | 直接訪問 |
總之:實例方法的存在必需要有對象實例的存在,若是對象實例不存在,則實例方法也就沒有調用它的主人。靜態方法的存在前提是類的存在,因此無需聲明和New對象。
class Program { static void Main(string[] args) { Class1.CallObjectFunc();//靜態調用 Console.WriteLine(Environment.NewLine); Class1 tmpClass = new Class1();//實例調用 tmpClass.ObjectFunc(); Console.ReadKey(); } } class Class1 { static int Class_m = 9;//靜態成員 private int object_m = 8;//實例成員 public static void CallObjectFunc() { Console.WriteLine("------------靜態方法調用開始:"); Class1 class1 = new Class1(); class1.ObjectFunc(); Console.WriteLine("object_m:" + class1.object_m.ToString()); Console.WriteLine("------------靜態方法調用結束:"); } public void ObjectFunc() { Console.WriteLine("實例方法調用開始:"); Console.WriteLine("Class_m:" + Class_m.ToString()); Console.WriteLine("實例方法調用結束:"); } }
輸出結果:
靜態類的主要功能以下:
它們僅包含靜態成員。----函數成員和變量都必須有static修飾
它們不能被實例化。
它們是密封的。-----------編譯器編譯時自動生成sealed標記
它們不能包含實例構造函數。
所以建立靜態類與建立僅包含靜態成員和私有構造函數的類大體同樣。私有構造函數阻止類被實例化。
使用靜態類的優勢在於,編譯器可以執行檢查以確保不致偶然地添加實例成員。編譯器將保證不會建立此類的實利。
靜態類是密封的,所以不可被繼承。靜態類不能包含構造函數,但仍可聲明靜態構造函數以分配初始值或設置某個靜態狀態。
靜態類:
static class CompanyInfo { public static string GetCompanyName() { return "CompanyName"; } public static string GetCompanyAddress() { return "CompanyAddress"; } }
(1)語法區別:靜態成員有關鍵字static,非靜態成員無static修飾;
(2)存儲區別: 靜態成員變量存儲位於程序的全局變量存儲區,其做用域限制爲類內部,而且在整個程序運行期間只在內存中擁有一個存儲位置,不會拷貝不會複製,只是一個;
非靜態成員變量存儲位於對象的變量存儲區,多個對象擁有多個變量的存儲,只隸屬於本身的的對象
(3)歸屬區別:靜態成員隸屬於類,是類的財產,不管對一個類建立多少個實例,它的靜態成員都只有一個副本,在各個地方的改變都會改變其值;
非靜態成員隸屬於它的對象,各自對象同一個非靜態成員值的改變都不互相影響,有多少實例就有多少副本;
(4)生存週期區別: 知道了存儲位置的區別也就不難理解生存週期的差別了,靜態成員只要分配了空間則在整個程序運行期間,它都是存在的,只有程序關閉以後,它的內存纔會被GC回收器收回,不過做用域仍然只限制於類的內部,在類外部調用時須要使用類 名加點的方式訪問;
類的非靜態成員的生存週期跟隨於隸屬於對象的生存週期,對象消亡則非靜態成員就會被回收;
(5)初始化順序的區別:初始化都是最早初始化類的靜態成員,而後纔是非靜態數據成員。
下面代碼的輸出是多少呢?先本身思考
using System; using System.Collections.Generic; using System.Linq; using System.Text; class class1 { private static int i = getNum(); private static int num = 1; int j = getNum(); private static int getNum() { return num; } static void Main(string[] args) { Console.WriteLine("i={0}", i); class1 class1Object = new class1();//默認構造函數 Console.WriteLine("j={0}", class1Object.j); Console.WriteLine("i={0}", i); Console.ReadKey(); } }
輸出結果爲:
額,怎麼回事這樣呢?是否是會和你想的不同,若是你真有這種想法,說明還須要看我下面的分析噢
類結構:這個類有三個變量,兩個私有靜態成員變量i和num,一個非靜態成員變量j;一個私有靜態函數getNum(),一個函數入口Main()
程序執行過程:首先以前說了初始化會首先初始化類的靜態變量。
i分配空間並初始化值爲0-->num分配空間並初始化爲0-->i賦值(調用getNum函數,此時num爲0,返回值爲0,因此i=0)-->num賦值爲1-->Main函數
至於Main函數內執行時,爲何i輸出不是1呢?這是由於靜態成員只初始化一次,因此此時調用i並不會再調用getNum()函數爲其賦值,此時的調用i是獲取i分配空間上的值。
(題外:初學程序的人鬧不清楚變量聲明、分配空間和賦值的概念,C#是強類型語言,分配空間就是爲變量分配符合變量前類型修飾符的空間大小,int就分配四字節,char就分配1字節,關於聲明和賦值不在本文探討範圍內,讀者可自行百度)
因爲本人才學識前,描述不免紕漏,若有錯誤,歡迎指出。部分引用和參考沒法詳細查證,若遇本尊駕臨,可告知,將附上引用地址和出處,麼麼!