日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

静态与非静态(转改)

發(fā)布時(shí)間:2023/11/30 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 静态与非静态(转改) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這里有一個(gè)C++的測(cè)試,由于c#的sizeof不能對(duì)一般類使用,所以沒(méi)法試驗(yàn)。

class Test {int i;static int j;void Method1() { printf("Method1"); };void Method2() { printf("Method2"); };void Method3() { printf("Method3"); };void Method4() { printf("Method4"); };void Method5() { printf("Method5"); };void Method7() { printf("Method7"); };void Method8() { printf("Method8"); };void Method9() { printf("Method9"); };static void Method10() { printf("Method10"); }; };int _tmain(int argc, _TCHAR* argv[]) {Test t;printf("size of Test: %d \r\n", sizeof(t));getchar(); return 0; }

這個(gè)類的測(cè)試結(jié)果是4,靜態(tài)方法無(wú)論有多少個(gè)都剛開(kāi)始都不占用內(nèi)存空間。

一、靜態(tài)方法常駐內(nèi)存,非靜態(tài)方法只有使用的時(shí)候才分配內(nèi)存?
???? 一般都認(rèn)為是這樣,并且怕靜態(tài)方法占用過(guò)多內(nèi)存而建議使用非靜態(tài)方法,其實(shí)這個(gè)理解是錯(cuò)誤的。為什么會(huì)這樣,先從內(nèi)存分配開(kāi)始說(shuō)起:托管堆的定義:對(duì)于32位的應(yīng)用程序來(lái)說(shuō),應(yīng)用程序完成進(jìn)程初始化后,CLR將在進(jìn)程的可用地址空間分配一塊保留的地址空間,它是進(jìn)程(每個(gè)進(jìn)程可使用4GB)中可用地址空間上的一塊內(nèi)存區(qū)域,但并不對(duì)應(yīng)任何物理內(nèi)存,這塊地址空間即是托管堆。托管堆有分為多個(gè)區(qū)域,其中最重要的是垃圾回收堆(GC Heap)和加載堆(Loader Heap),GC Heap用于存儲(chǔ)對(duì)象實(shí)例,受GC管理;Loader Heap又分為High-Frequency Heap、Low-Frequency Heap和Stub Heap,不同的堆上又存儲(chǔ)不同的信息。Loader Heap最重要的信息就是元數(shù)據(jù)相關(guān)的信息,也就是Type對(duì)象,每個(gè)Type在Loader Heap上體現(xiàn)為一個(gè)Method Table(方法表),而Method Table中則記錄了存儲(chǔ)的元數(shù)據(jù)信息,例如基類型、靜態(tài)字段、實(shí)現(xiàn)的接口、所有的方法等等。Loader Heap不受GC控制,其生命周期為從創(chuàng)建到AppDomain卸載。(摘自《你必須知道的.Net》)由此我們就明白了,靜態(tài)方法和非靜態(tài)方法,在內(nèi)存里其實(shí)都放在Method Table里了,在一個(gè)類第一次被加載的時(shí)候,它會(huì)在Loader Heap里把靜態(tài)方法,非靜態(tài)方法都寫入Method Table中,而且Loader Heap不受GC控制,所以一旦加載,GC就不會(huì)回收,直到AppDomain卸載由此我們也明白了,靜態(tài)方法和非靜態(tài)方法,他們都是在第一次加載后就常駐內(nèi)存,所以方法本身在內(nèi)存里,沒(méi)有什么區(qū)別,所以也就不存在”靜態(tài)方法常駐內(nèi)存,非靜態(tài)方法只有使用的時(shí)候才分配內(nèi)存“這個(gè)結(jié)論了。
二、靜態(tài)方法和非靜態(tài)方法的區(qū)別?
??? 在內(nèi)存中的區(qū)別是,非靜態(tài)方法在創(chuàng)建實(shí)例對(duì)象時(shí),因?yàn)閷傩缘闹祵?duì)于每個(gè)對(duì)象都各不相同,因此在new一個(gè)實(shí)例時(shí),會(huì)把這個(gè)實(shí)例屬性在GC Heap里拷貝一份,同時(shí)這個(gè)new出來(lái)的對(duì)象放在堆棧上,堆棧指針指向了剛才拷貝的那一份實(shí)例的內(nèi)存地址上。而靜態(tài)方法則不需要,因?yàn)殪o態(tài)方法里面的靜態(tài)字段,就是保存在Method Table里了,只有一份。因此靜態(tài)方法和非靜態(tài)方法,在調(diào)用速度上,靜態(tài)方法速度一定會(huì)快點(diǎn),因?yàn)榉庆o態(tài)方法需要實(shí)例化,分配內(nèi)存,但靜態(tài)方法不用,但是這種速度上差異可以忽略不計(jì)。
三、為什么要有非靜態(tài)方法?
?? 早期的結(jié)構(gòu)化編程,幾乎所有的方法都是“靜態(tài)方法”,引入實(shí)例化方法概念是面向?qū)ο蟾拍畛霈F(xiàn)以后的事情了,區(qū)分靜態(tài)方法和實(shí)例化方法不能單單從性能上去理解,創(chuàng)建c++,java,c#這樣面向?qū)ο笳Z(yǔ)言的大師引入實(shí)例化方法一定不是要解決什么性能、內(nèi)存的問(wèn)題,而是為了讓開(kāi)發(fā)更加模式化、面向?qū)ο蠡_@樣說(shuō)的話,靜態(tài)方法和實(shí)例化方式的區(qū)分是為了解決模式的問(wèn)題。接下來(lái)繼續(xù)思考,如果我們?nèi)坑渺o態(tài)方法,不用非靜態(tài)方法,不是一樣能實(shí)現(xiàn)功能嗎?是的,沒(méi)錯(cuò),但是你的代碼是基于對(duì)象,而不是面向?qū)ο蟮?#xff0c;因?yàn)槊嫦驅(qū)ο蟮睦^承和多態(tài),都是非靜態(tài)方法。第二個(gè)原因是為什么不建議都用靜態(tài)方法,我們?nèi)绻嗑€程的情況下,如果靜態(tài)方法使用了一個(gè)靜態(tài)字段,這個(gè)靜態(tài)字段可以會(huì)被多個(gè)線程修改,因此說(shuō)如果在靜態(tài)方法里使用了靜態(tài)變量,這就會(huì)有線程安全問(wèn)題,當(dāng)然了,就算不是多線程,因?yàn)殪o態(tài)字段只有一份,同樣會(huì)有被其他地方修改的問(wèn)題。
從這三點(diǎn)我們得出的結(jié)論如下:
一、 什么時(shí)候用靜態(tài)方法,什么時(shí)候使用非靜態(tài)方法?
??? 既然靜態(tài)方法和實(shí)例化方式的區(qū)分是為了解決模式的問(wèn)題,如果我們考慮不需要繼承和多態(tài)的時(shí)候,就可以使用靜態(tài)方法,但就算不考慮繼承和多態(tài),就一概使用靜態(tài)方法也不是好的編程思想。從另一個(gè)角度考慮,如果一個(gè)方法和他所在類的實(shí)例對(duì)象無(wú)關(guān),那么它就應(yīng)該是靜態(tài)的,否則就應(yīng)該是非靜態(tài)。因此像工具類,一般都是靜態(tài)的。
二、 為什么使用單例模式而不用靜態(tài)方法?
??? 從面相對(duì)象的角度講:雖然都能實(shí)現(xiàn)目的,但是他們一個(gè)是基于對(duì)象,一個(gè)是面向?qū)ο蟮?#xff0c;就像我們不面相對(duì)象也能解決問(wèn)題一樣,面相對(duì)象的代碼提供一個(gè)更好的編程思想。如果一個(gè)方法和他所在類的實(shí)例對(duì)象無(wú)關(guān),那么它就應(yīng)該是靜態(tài)的,反之他就應(yīng)該是非靜態(tài)的。如果我們確實(shí)應(yīng)該使用非靜態(tài)的方法,但是在創(chuàng)建類時(shí)又確實(shí)只需要維護(hù)一份實(shí)例時(shí),就需要用單例模式了。比如說(shuō)我們?cè)谙到y(tǒng)運(yùn)行時(shí)候,就需要加載一些配置和屬性,這些配置和屬性是一定存在了,又是公共的,同時(shí)需要在整個(gè)生命周期中都存在,所以只需要一份就行,這個(gè)時(shí)候如果需要我再需要的時(shí)候new一個(gè),再給他分配值,顯然是浪費(fèi)內(nèi)存并且再賦值沒(méi)什么意義,所以這個(gè)時(shí)候我們就需要單例模式或靜態(tài)方法去維持一份且僅這一份拷貝,但此時(shí)這些配置和屬性又是通過(guò)面向?qū)ο蟮木幋a方式得到的,我們就應(yīng)該使用單例模式,或者不是面向?qū)ο蟮?#xff0c;但他本身的屬性應(yīng)該是面對(duì)對(duì)象的,我們使用靜態(tài)方法雖然能同樣解決問(wèn)題,但是最好的解決方案也應(yīng)該是使用單例模式。從功能上講:單例模式可以控制單例數(shù)量;可以進(jìn)行有意義的派生;對(duì)實(shí)例的創(chuàng)建有更自由的控制;
三、其他:
??? 數(shù)據(jù)庫(kù)連接能不能做SingleTon?如果是簡(jiǎn)單地把一個(gè)connection對(duì)象封存在單例對(duì)象中,這樣是錯(cuò)誤的,因此連接池里有多個(gè)鏈接可以用,如果使用SingleTon,那在WEB訪問(wèn)時(shí),就只能用一個(gè)數(shù)據(jù)庫(kù)鏈接,那不是死的很慘?但是鏈接池可以使用單例模式,初始化的時(shí)候創(chuàng)建譬如100個(gè)connection對(duì)象,然后再需要的時(shí)候提供一個(gè),用過(guò)之后返回到pool中,我們用單例模式,是保證連接池有且只有一個(gè)。再舉個(gè)例子,比如DAL層寫好一個(gè)調(diào)用數(shù)據(jù)庫(kù)表的類,在BLL層應(yīng)用此類時(shí),如果每次都new創(chuàng)建的話需要頻繁的創(chuàng)建和回收,而DAL層這個(gè)類里又沒(méi)有和對(duì)象相關(guān)的值變量,所以不需要每次都new一個(gè),這時(shí)候就可以用單例模式來(lái)創(chuàng)建這個(gè)DAL實(shí)例。

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/zyizyizyi/archive/2013/02/20/2918008.html

總結(jié)

以上是生活随笔為你收集整理的静态与非静态(转改)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。