更新時間:2018-09-12 來源:黑馬程序員JavaEE培訓(xùn)學(xué)院 瀏覽量:
【Java】——static關(guān)鍵字
static是什么???——》一個修飾符
那static作用于那???——》用于修飾成員
什么是成員???——》成員變量和成員函數(shù)
static修飾成員變量
static為什么修飾成員變量???——》解決數(shù)據(jù)的共享問題???——》static修飾的數(shù)據(jù)可以被每個對象共享的數(shù)據(jù)
為什么需要被每個對象共享某個數(shù)據(jù)???——》如果所有對象中某一個屬性的值是一樣的,那么在內(nèi)存中會造成大量的數(shù)據(jù)重復(fù);
那怎么實現(xiàn)static的作用???——》
被修飾后的成員變量的存儲如圖所示:
被static修飾后的成員變量的存儲在哪里???——》即不在堆里也不在棧里,而是在方法區(qū)的靜態(tài)區(qū)里
靜態(tài)區(qū)???——》放一些靜態(tài)變量和靜態(tài)方法。
存放好了,那該如何調(diào)用這種數(shù)據(jù)(或方法)?——》類名調(diào)用
既然知道了static是什么和如何運用等;那么我們也該了解靜態(tài)變量和成員變量有什么區(qū)別???——》
·1)、別名不同???——》成員變量也稱為實例變量;靜態(tài)變量也稱為類變量。
·2)、兩個變量的生命周期不同???——》也是靜態(tài)的弊端,生命周期太長,但是也好過占用內(nèi)存;——》成員變量隨著對象的創(chuàng)建而存在,隨著對象的回收而被釋放;
·3)、靜態(tài)變量隨著類的加載而存在,會隨著類的消失而消失???——》虛擬機結(jié)束了,類才會消失,并且類本身是一個對象,在內(nèi)存里面也是按照對象的形式存儲的,只不過可以通過這個類對象創(chuàng)建很多對象來封裝具體的數(shù)據(jù);
·4)、當(dāng)類的數(shù)據(jù)過多的時候,垃圾回收機制可以對舊數(shù)據(jù)進行回收???——》當(dāng)再次使用再重新加載,如果類很長時間不用就把它清除;
·5)、調(diào)用方式不同???——》成員變量只能被對象調(diào)用;——》靜態(tài)變量可以被對象調(diào)用,還可以被類名調(diào)用;
·注意:不管有沒有對象,都建議用類名調(diào)用???——》這是靜態(tài)的專屬調(diào)用方式,可閱讀性強,讓人看了一目了然,知道這是靜態(tài)變量;
·6)、類的類型變量與類變量不是一碼事???——》類的類型變量是由類定義的變量,類變量就是靜態(tài)變量;
·7)、數(shù)據(jù)存儲位置不同???——》成員變量數(shù)據(jù)存儲在堆內(nèi)存的對象中,所以也叫對象的特有數(shù)據(jù);——》靜態(tài)變量數(shù)據(jù)存儲在方法區(qū)的靜態(tài)區(qū)中,所以也叫對象的共享數(shù)據(jù);
注意:
方法區(qū)???——》也叫共享區(qū),數(shù)據(jù)區(qū)·····翻譯的名字多著呢,還記得之前五個區(qū)不?
方法存在方法區(qū),調(diào)用時進棧;
當(dāng)static修飾成員函數(shù)
為什么static要修飾成員函數(shù)使之成為一個靜態(tài)函數(shù)???——》這是因為static有其作用之處;
靜態(tài)函數(shù)作用于哪里???——》可以直接訪問靜態(tài)成員,靜態(tài)方法;但是如果要訪問成員方法,只能通過對象訪問;
為什么靜態(tài)成員的出現(xiàn)比對象要早???——》靜態(tài)變量和靜態(tài)方法都是存放在靜態(tài)區(qū)中的,會隨著類的加載而加載
如何使靜態(tài)函數(shù)調(diào)用非靜態(tài)方法(或靜態(tài)變量)???——》必須要在靜態(tài)函數(shù)內(nèi)部創(chuàng)建一個對象???——》以確保對象是和靜態(tài)方法是一起出現(xiàn)的;???——》對象才調(diào)用非靜態(tài)的方法和變量;
使用static修飾成員函數(shù)該注意以下幾點:
1.靜態(tài)方法只能訪問靜態(tài)成員(包含成員變量成員函數(shù)),非靜態(tài)既可以訪問靜態(tài)又可以訪問非靜態(tài);
2.靜態(tài)方法中不可以定義this(寫this是會報錯的)???——》因為用類名調(diào)用靜態(tài)方法時沒有對象,所以this沒有指向;
三句話圖解static在內(nèi)存中的姿勢:
首先我們先來分析這段代碼:
當(dāng)我們執(zhí)行StaticDemo2的字節(jié)碼文件的時候,這個類被加載進內(nèi)存,然后進行空間的開辟,不同種類數(shù)據(jù)存放在不一樣的地方。
方法區(qū)里有一個靜態(tài)區(qū),存放靜態(tài)方法和數(shù)據(jù),非靜態(tài)區(qū)里存放非靜態(tài)的方法和數(shù)據(jù),它們都是被共享的。
非靜態(tài)區(qū)里面都有一個this所屬,內(nèi)容只能被對象調(diào)用;
靜態(tài)區(qū)里有一個所屬是自己的類名,沒有this,this是不能寫在靜態(tài)方法里的,所以此時,當(dāng)我們調(diào)用這個StaticDemo2類的時候,內(nèi)存的加載如下:
當(dāng)運行到主函數(shù)的時候,主函數(shù)進棧:
第一句話:使用到了Person類,此時找classPath路徑下是否有Person.class文件,如果沒有設(shè)置classPath,默認在當(dāng)前路徑下找,找到Person文件后加載Person類,加載完畢后,運行method()方法,method()方法進棧,語句執(zhí)行完畢,運行默認的return語句,方法出棧。
第二句話:在主函數(shù)中定義一個Person類型的變量p,在堆中創(chuàng)建一個新對象,為對象分配地址,堆內(nèi)存對對象進行數(shù)據(jù)初始化,然后傳參數(shù)進行構(gòu)造函數(shù)初始化,構(gòu)造函數(shù)進棧,執(zhí)行完畢彈棧。
第三句話:p.show()在編譯運行之前都要檢查是否有show()方法,如果有show()方法,show()方法進棧,并且show()方法是非靜態(tài)的方法,所以show()方法里也應(yīng)該有默認的this引用,此時this的值是所屬的函數(shù)的調(diào)用對象的值,在輸出語句中可以通過類的所屬找到country,通過this找到name和age。執(zhí)行完畢后結(jié)束函數(shù) 不加靜態(tài)是在對象里,加了靜態(tài)是在方法區(qū)里;
不加靜態(tài)是特定對象特有,加了靜態(tài)對象共有。
對象的特有數(shù)據(jù),必須存儲在對象中???——》數(shù)據(jù)在對象中都是不同,不能使用static修飾;
簡單點說,從源代碼看,該功能是否需要訪問非靜態(tài)的成員變量,如果需要,該功能就是非靜態(tài)的。如果不需要,就可以將該功能定義成靜態(tài)的,當(dāng)然也可以定義成非靜態(tài),但是非靜態(tài)需要被對象調(diào)用,而僅創(chuàng)建對象調(diào)用非靜態(tài)的方法,沒有訪問特有數(shù)據(jù),該對象的創(chuàng)建是沒有意義的。
首發(fā):http://java.itheima.com/