當類的字節(jié)碼被加載到內(nèi)存時,實例方法不會被分配入口地址,只有該類創(chuàng)建對象時,類中的實例方法才分配入口地址,所以實例方法只能通過對象調(diào)用。 而類方法是當類加載到內(nèi)存中,就分配了相應(yīng)的內(nèi)存地址,所以類方法不僅可以通過對象調(diào)用,也可以用類名調(diào)用。 靜態(tài)方法(Static Method)和非靜態(tài)方法(Non-Static Method)的區(qū)別總結(jié)如下: 靜態(tài)方法在類裝載的時候被裝載到內(nèi)存(Memory),不自動進行銷毀,會一直存在于內(nèi)存中,直到JVM關(guān)閉。 非靜態(tài)方法在實例化后才會分配內(nèi)存,當實例對象被JVM 回收之后,也跟著消失,不會常駐內(nèi)存。 6、靜態(tài)方法和靜態(tài)變量創(chuàng)建后始終使用同一塊內(nèi)存,而使用實例的方式會創(chuàng)建多個內(nèi)存。
上面這個類中的getType方法,在沒有new對象前這就可以這樣用: 轉(zhuǎn)自 https://zhidao.baidu.com/question/1433773942389340379.html 靜態(tài)方法何時使用
這些各種說法,基本上都是正確的。 歡迎關(guān)注公眾號"Devin說",會不定期更新技術(shù)知識。 轉(zhuǎn)自 https://www.cnblogs.com/devinzhang/archive/2012/04/27/2473570.html 靜態(tài)代碼塊靜態(tài)代碼塊指 Java 類中的 static{...} 代碼塊,主要用于初始化類,為類的靜態(tài)變量賦初始值。
注意:變量指基本數(shù)據(jù)類型非對象,局部變量不能被靜態(tài)修飾 1、(靜態(tài))成員變量存放在data segment區(qū)(數(shù)據(jù)區(qū)),字符串常量也存放在該區(qū) 2、非靜態(tài)變量,new出來的對象存放在堆內(nèi)存,所有局部變量和引用地址存放在棧內(nèi)存 3、方法(包括靜態(tài)方法)存放在code segment(方法塊),存放代碼片段,且只存放一次 ![]()
![]() 靜態(tài)方法和實例方法區(qū)別及使用場景從實際項目開發(fā)說起,這里有開發(fā)項目的三種方式: 開發(fā)項目中把BLL和DAL分開,在BLL調(diào)用DAL的代碼。 一、在DAL中使用靜態(tài)方法,不創(chuàng)建實例直接調(diào)用(大概有很多人都使用這種方式開發(fā) ) class DAL { public static string GetUserName(…); } 在BLL中調(diào)用: DAL.GetUserName(); 二、在DAL中使用實例方法,采用靜態(tài)成員模式(或Singleton)通過實例來調(diào)用: class DAL { public static readonly DAL dal = new DAL(); public string GetUserName(…); } 在BLL中調(diào)用: DAL.dal.GetUserName(); 三、在DAL中使用實例方法,每次調(diào)用之前先創(chuàng)建DAL對象的實例: class DAL { public string GetUserName(…); } 在BLL中調(diào)用: DAL dal = new DAL(); dal.GetUserName(); 開發(fā)方式一:我以為在一些情況下(比如 調(diào)用多個數(shù)據(jù)庫、GetUserName(…)內(nèi)部處理操作部分)會出現(xiàn)線程安全的嫌疑。這種開發(fā)方式不用New出對象,所以很普遍。 開發(fā)方式二:應(yīng)該多是應(yīng)用在cs模式下,DAL在整個項目只會有一個對象存在,如果出現(xiàn)在B/S 我想不能兼容多種問題情況。而且也有線程安全的問題。 開發(fā)方式三:應(yīng)該是普遍使用的,能夠兼容各種問題,也不會有線程不安全的嫌疑出現(xiàn)。 特別說明一下:在MS的pet3.0以前的版本 都采用了方式二,而到pet3.0和以后的版本 都采用了方式三,而且特別在開發(fā)說明文檔中明確的解釋了一下。我想應(yīng)該是從兼容性上考慮的,從性能上方式二并不比方式三真正的高多少。 我特意以“你怎么理解并使用靜態(tài)方法和實例化方法的?”這樣的問題詢問了多位程序員,他們開發(fā)的語言也不盡相同(c 、c++、java、c#) 以下是他們的回答:
有時候我們對靜態(tài)方法和實例化方法會有一些誤解。 1、大家都以為“ 靜態(tài)方法常駐內(nèi)存,實例方法不是,所以靜態(tài)方法效率高但占內(nèi)存?!?nbsp; 事實上,他們都是一樣的,在加載時機和占用內(nèi)存上,靜態(tài)方法和實例方法是一樣的,在類型第一次被使用時加載。調(diào)用的速度基本上沒有差別。 2、大家都以為“ 靜態(tài)方法在堆上分配內(nèi)存,實例方法在堆棧上” 事實上所有的方法都不可能在堆或者堆棧上分配內(nèi)存,方法作為代碼是被加載到特殊的代碼內(nèi)存區(qū)域,這個內(nèi)存區(qū)域是不可寫的。 方法占不占用更多內(nèi)存,和它是不是static沒什么關(guān)系。 因為字段是用來存儲每個實例對象的信息的,所以字段會占有內(nèi)存,并且因為每個實例對象的狀態(tài)都不一致(至少不能認為它們是一致的),所以每個實例對象的所有字段都會在內(nèi)存中有一分拷貝,也因為這樣你才能用它們來區(qū)分你現(xiàn)在操作的是哪個對象。 但方法不一樣,不論有多少個實例對象,它的方法的代碼都是一樣的,所以只要有一份代碼就夠了。因此無論是static還是non-static的方法,都只存在一份代碼,也就是只占用一份內(nèi)存空間。 同樣的代碼,為什么運行起來表現(xiàn)卻不一樣?這就依賴于方法所用的數(shù)據(jù)了。主要有兩種數(shù)據(jù)來源,一種就是通過方法的參數(shù)傳進來,另一種就是使用class的成員變量的值…… 3、大家都以為“實例方法需要先創(chuàng)建實例才可以調(diào)用,比較麻煩,靜態(tài)方法不用,比較簡單” 事實上如果一個方法與他所在類的實例對象無關(guān),那么它就應(yīng)該是靜態(tài)的,而不應(yīng)該把它寫成實例方法。所以所有的實例方法都與實例有關(guān),既然與實例有關(guān),那么創(chuàng)建實例就是必然的步驟,沒有麻煩簡單一說。 當然你完全可以把所有的實例方法都寫成靜態(tài)的,將實例作為參數(shù)傳入即可,一般情況下可能不會出什么問題。 從面向?qū)ο蟮慕嵌壬蟻碚f,在抉擇使用實例化方法或靜態(tài)方法時,應(yīng)該根據(jù)是否該方法和實例化對象具有邏輯上的相關(guān)性,如果是就應(yīng)該使用實例化對象 反之使用靜態(tài)方法。這只是從面向?qū)ο蠼嵌壬蟻碚f的。 如果從線程安全、性能、兼容性上來看 也是選用實例化方法為宜。 我們?yōu)槭裁匆逊椒▍^(qū)分為:靜態(tài)方法和實例化方法 ? 如果我們繼續(xù)深入研究的話,就要脫離技術(shù)談理論了。早期的結(jié)構(gòu)化編程,幾乎所有的方法都是“靜態(tài)方法”,引入實例化方法概念是面向?qū)ο蟾拍畛霈F(xiàn)以后的事情了,區(qū)分靜態(tài)方法和實例化方法不能單單從性能上去理解,創(chuàng)建c++,java,c#這樣面向?qū)ο笳Z言的大師引入實例化方法一定不是要解決什么性能、內(nèi)存的問題,而是為了讓開發(fā)更加模式化、面向?qū)ο蠡_@樣說的話,靜態(tài)方法和實例化方式的區(qū)分是為了解決模式的問題。 拿別人一個例子說事: 比如說“人”這個類,每個人都有姓名、年齡、性別、身高等,這些屬性就應(yīng)該是非靜態(tài)的,因為每個人都的這些屬性都不相同;但人在生物學上屬于哪個門哪個綱哪個目等,這個屬性是屬于整個人類,所以就應(yīng)該是靜態(tài)的——它不依賴與某個特定的人,不會有某個人是“脊椎動物門哺乳動物綱靈長目”而某個人卻是“偶蹄目”的。 |
|