進一步理解靜態方法與實例方法的區別和實際應用


進一步理解靜態方法與實例方法的區別和實際應用

標簽(空格分隔): CSharp

以前對靜態方法與實例方法的理解,僅限於知道靜態方法不需要實例化對象就可以被直接調用,且靜態方法在內存中只存一份,是全局性的,而實例化方法則必須實例化對象才能被調用,且在內存中每實例化一次就存一份。平時對靜態方法的使用也比較少,一般也只在寫一些公共使用的工具類方法的時候才用到,大部分時候都是操作實例化方法比較多。最近對閱讀了一些有關靜態方法和實例方法方面的技術文章,對其區別和實際應用進行了進一步的理解。

1、網絡上對靜態方法和實例方法的一些認識

下面分別列出了各個軟件攻城獅們對靜態方法與實例方法的認識,這些主要來源於志良的技術博客

  • A君認為兩者之間幾乎沒有區別,在不需要實例化的情況下,就使用靜態方法,在需要考慮穩妥的情況下,則需要使用實例方法,這樣才可調用其他實例方法和變量。
  • B君認為在寫公共的方法,且是零散的方法的時候,一般使用靜態方法。
  • C君認為靜態方法使用的比較少,因為其在應用一啟動就實例化了,比較占資源。但是其在配合單例模式使用的時候比較好用,此外,比較多的使用在數據連接上。
  • D君認為靜態就是類的,實例就是對象的。此外,靜態方法不需要依賴類當中的屬性,能在這個方法中封閉的完成一個功能,而實例方法更多的會使用到類當中的屬性。
  • E君認為兩者最大的區別在於內存。靜態方法在程序開始時生成內存,實例方法在程序運行中生成內存,所以靜態方法可以直接調用,實例方法要先生成實例,通過實例調用方法,靜態速度很快,但是多可會占內存。任何語言都是對內存和磁盤的操作,至於是否面向對象,只是軟件層的問題,底層都是一樣的,只是實現方法不同。靜態內存是連續的,因為是在程序開始時就生成了,而實例申請的是離散的空間,所以沒有靜態方法快。而且靜態內存是有限制的,太多了程序會啟動不了。
  • F君認為靜態方法與實例方法各有自己的用處。到底是定義成靜態方法,還是定義成實例方法,還要看具體情況,比如方法本身與類型沒有太大的關系,可以定義成靜態方法。使用實例方法時,則需要先創建實例,才能調用實例方法,而靜態方法則不需要。從性能上來說,靜態方法效率要稍微高一些,但是它會常駐內存。一些情況下使用靜態方法是有好處的,因為靜態方法無論你有多少實例,內存中只要維護一份拷貝。
  • G君認為兩者牽扯到的東西比較多,諸如設計模式等等。簡單點說,靜態方法用來執行無狀態的一個完整操作,實例方法則相反,它通常是一個完整邏輯的一部分,並且需要維護一定的狀態值。如果用內存和效率來區分使用靜態方法和實例方法就回到過去結構化編程了。使用那種方法的根本出發點還是圍繞面向對象來進行的。

2、對靜態方法和實例方法的進一步理解

從上述可知,大家都覺得實例化方法使用更多且穩妥些,靜態方法盡量少用。
對靜態方法與實例方法新理解:
1、靜態方法常駐內存,實例方法則不是,所以靜態方法效率高但占內存?
事實上,他們都是一樣的,在加載時機和占用內存上,靜態方法和實例方法是一樣的,在類型第一次被使用時加載。調用的速度基本上沒有差別。
2、靜態方法在堆上分配內存,實例方法在堆棧上?
事實上所有的方法都不可能在堆或者堆棧上分配內存,方法作為代碼是被加載到特殊的代碼內存區域,這個內存區域是不可寫的。
方法占不占用更多內存,和它是不是static沒什么關系。
因為字段是用來存儲每個實例對象的信息的,所以字段會占有內存,並且因為每個實例對象的狀態都不一致(至少不能認為它們是一致的),所以每個實例對象的所以字段都會在內存中有一分拷貝,也因為這樣你才能用它們來區分你現在操作的是哪個對象。
但方法不一樣,不論有多少個實例對象,它的方法的代碼都是一樣的,所以只要有一份代碼就夠了。因此無論是static還是non-static的方法,都只存在一份代碼,也就是只占用一份內存空間。
同樣的代碼,為什么運行起來表現卻不一樣?這就依賴於方法所用的數據了。主要有兩種數據來源,一種就是通過方法的參數傳進來,另一種就是使用class的成員變量的值……
3、實例方法需要先創建實例才可以調用,比較麻煩,靜態方法不用,比較簡單?
事實上如果一個方法與他所在類的實例對象無關,那么它就應該是靜態的,而不應該把它寫成實例方法。所以所有的實例方法都與實例有關,既然與實例有關,那么創建實例就是必然的步驟,沒有麻煩簡單一說。
當然你完全可以把所有的實例方法都寫成靜態的,將實例作為參數傳入即可,一般情況下可能不會出什么問題。
從面向對象的角度上來說,在抉擇使用實例化方法或靜態方法時,應該根據是否該方法和實例化對象具有邏輯上的相關性,如果是就應該使用實例化對象 反之使用靜態方法。這只是從面向對象角度上來說的。
如果從線程安全、性能、兼容性上來看 也是選用實例化方法為宜。
4、為什么要把方法區分為:靜態方法和實例化方法?
如果我們繼續深入研究的話,就要脫離技術談理論了。早期的結構化編程,幾乎所有的方法都是“靜態方法”,引入實例化方法概念是面向對象概念出現以后的事情了,區分靜態方法和實例化方法不能單單從性能上去理解,創建c++,java,c#這樣面向對象語言的大師引入實例化方法一定不是要解決什么性能、內存的問題,而是為了讓開發更加模式化、面向對象化。這樣說的話,靜態方法和實例化方式的區分是為了解決模式的問題。
拿別人一個例子說事:
比如說“人”這個類,每個人都有姓名、年齡、性別、身高等,這些屬性就應該是非靜態的,因為每個人都的這些屬性都不相同;但人在生物學上屬於哪個門哪個綱哪個目等,這個屬性是屬於整個人類,所以就應該是靜態的——它不依賴與某個特定的人,不會有某個人是“脊椎動物門哺乳動物綱靈長目”而某個人卻是“偶蹄目”的。

2.2、靜態方法與實例方法在內存中

代碼例子:

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person();
        Person p1 = new Person();
        Person p2 = new Person();
    }
}

class Person
{
    //靜態成員變量
    private static int nAge;
    //實例成員變量
    private string strName;

    public static void Run()
    {
        Console.WriteLine("我會奔跑!");
    }

    public void Sing()
    {
        Console.WriteLine("我會唱歌");
    }
}

靜態方法與實例方法在內存中:
此處輸入圖片的描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM