Java基礎(chǔ)知識(shí)學(xué)習(xí)——static關(guān)鍵字

一、static關(guān)鍵字

原來(lái)一個(gè)類里面的成員變量,每new一個(gè)對(duì)象,這個(gè)對(duì)象就有一份自己的成員變量,因?yàn)檫@些成員變量都不是靜態(tài)成員變量。對(duì)于static成員變量來(lái)說(shuō),這個(gè)成員變量只有一份,而且這一份是這個(gè)類所有的對(duì)象共享。

1.1.靜態(tài)成員變量與非靜態(tài)成員變量的區(qū)別

?以下面的例子為例說(shuō)明

通過(guò)畫(huà)內(nèi)存分析圖了解整個(gè)程序的執(zhí)行過(guò)程

執(zhí)行程序的第一句話:Cat.sid=?100;時(shí),這里的sid是一個(gè)靜態(tài)成員變量,靜態(tài)變量存放在數(shù)據(jù)區(qū)(data?seg),所以首先在數(shù)據(jù)區(qū)里面分配一小塊空間sid,第一句話執(zhí)行完后,sid里面裝著一個(gè)值就是100。

此時(shí)的內(nèi)存布局示意圖如下所示

接下來(lái)程序執(zhí)行到:

Cat??mimi?=?new?Cat(“mimi”);

這里,調(diào)用Cat類的構(gòu)造方法Cat(String?name),構(gòu)造方法的定義如下:

Cat?(?String?name){

this.name?=?name;

id=sid++;

}

調(diào)用時(shí)首先在棧內(nèi)存里面分配一小塊內(nèi)存mm,里面裝著可以找到在堆內(nèi)存里面的Cat類的實(shí)例對(duì)象的地址,mm就是堆內(nèi)存里面Cat類對(duì)象的引用對(duì)象。這個(gè)構(gòu)造方法聲明有字符串類型的形參變量,所以這里把“mimi”作為實(shí)參傳遞到構(gòu)造方法里面,由于字符串常量是分配在數(shù)據(jù)區(qū)存儲(chǔ)的,所以數(shù)據(jù)區(qū)里面多了一小塊內(nèi)存用來(lái)存儲(chǔ)字符串“mimi”。此時(shí)的內(nèi)存分布如下圖所示:

當(dāng)調(diào)用構(gòu)造方法時(shí),首先在棧內(nèi)存里面給形參name分配一小塊空間,名字叫name,接下來(lái)把”mimi”這個(gè)字符串作為實(shí)參傳遞給name,字符串也是一種引用類型,除了那四類8種基礎(chǔ)數(shù)據(jù)類型之外,其他所有的都是引用類型,所以可以認(rèn)為字符串也是一個(gè)對(duì)象。所以這里相當(dāng)于把”mimi”這個(gè)對(duì)象的引用傳遞給了name,所以現(xiàn)在name指向的是”mimi”。所以此時(shí)內(nèi)存的布局如下圖所示:

接下來(lái)執(zhí)行構(gòu)造方法體里面的代碼:

this.name=name;

這里的this指的是當(dāng)前的對(duì)象,指的是堆內(nèi)存里面的那只貓。這里把棧里面的name里面裝著的值傳遞給堆內(nèi)存里面的cat對(duì)象的name屬性,所以此時(shí)這個(gè)name里面裝著的值也是可以找到位于數(shù)據(jù)區(qū)里面的字符串對(duì)象“mimi”的,此時(shí)這個(gè)name也是字符串對(duì)象“mimi”的一個(gè)引用對(duì)象,通過(guò)它的屬性值就可以找到位于數(shù)據(jù)區(qū)里面的字符串對(duì)象“mimi”。此時(shí)的內(nèi)存分布如下圖所示:

接下來(lái)執(zhí)行方法體內(nèi)的另一句代碼:

id=sid++;

這里是把sid的值傳遞給id,所以id的值是100,sid傳遞完以后,自己再加1,此時(shí)sid變成了101。此時(shí)的內(nèi)存布局如下圖所示。

到此,構(gòu)造方法調(diào)用完畢,給這個(gè)構(gòu)造方法分配的局部變量所占的內(nèi)存空間全部都要消失,所以位于??臻g里面的name這塊內(nèi)存消失了。棧內(nèi)存里面指向數(shù)據(jù)區(qū)里面的字符串對(duì)象“mimi”的引用也消失了,此時(shí)只剩下堆內(nèi)存里面的指向字符串對(duì)象“mimi”的引用沒(méi)有消失。此時(shí)的內(nèi)存布局如下圖所示:

接下來(lái)執(zhí)行:Cat? pipi =new Cat(“pipi”);

這里是第二次調(diào)用構(gòu)造方法Cat(),整個(gè)調(diào)用過(guò)程與第一次一樣,調(diào)用結(jié)束后,此時(shí)的內(nèi)存布局如下圖所示:

最后兩句代碼是調(diào)用info()方法打印出來(lái),打印結(jié)果如下:

通過(guò)這個(gè)程序,看出來(lái)了這個(gè)靜態(tài)成員變量sid的作用,它可以計(jì)數(shù)。每當(dāng)有一只貓new出來(lái)的時(shí)候,就給它記一個(gè)數(shù)。讓它自己往上加1。

程序執(zhí)行完后,內(nèi)存中的整個(gè)布局就如上圖所示了。一直持續(xù)到main方法調(diào)用完成的前一刻。

這里調(diào)用構(gòu)造方法Cat(String?name)創(chuàng)建出兩只貓,首先在棧內(nèi)存里面分配兩小塊空間mimi和pipi,里面分別裝著可以找到這兩只貓的地址,mimi和pipi對(duì)應(yīng)著堆內(nèi)存里面的兩只貓的引用。這里的構(gòu)造方法聲明有字符串類型的變量,字符串常量是分配在數(shù)據(jù)區(qū)里面的,所以這里會(huì)把傳過(guò)來(lái)的字符串mimi和pipi都存儲(chǔ)到數(shù)據(jù)區(qū)里面。所以數(shù)據(jù)區(qū)里面分配有存儲(chǔ)字符串mimi和pipi的兩小塊內(nèi)存,里面裝著字符串“mimi”和“pipi”,字符串也是引用類型,除了那四類8種的基礎(chǔ)數(shù)據(jù)類型之外,其他所有的數(shù)據(jù)類型都是引用類型。所以可以認(rèn)為字符串也是一個(gè)對(duì)象。

這里是new了兩只貓出來(lái),這兩只貓都有自己的id和name屬性,所以這里的id和name都是非靜態(tài)成員變量,即沒(méi)有static修飾。所以每new出一只新貓,這只新貓都有屬于它自己的id和name,即非靜態(tài)成員變量id和name是每一個(gè)對(duì)象都有單獨(dú)的一份。但對(duì)于靜態(tài)成員變量來(lái)說(shuō),只有一份,不管new了多少個(gè)對(duì)象,哪怕不new對(duì)象,靜態(tài)成員變量在數(shù)據(jù)區(qū)也會(huì)保留一份。如這里的sid一樣,sid存放在數(shù)據(jù)區(qū),無(wú)論new出來(lái)了多少只貓?jiān)诙褍?nèi)存里面,sid都只有一份,只在數(shù)據(jù)區(qū)保留一份。

靜態(tài)成員變量是屬于整個(gè)類的,它不屬于專門的某個(gè)對(duì)象。那么如何訪問(wèn)這個(gè)靜態(tài)成員變量的值呢?首先第一點(diǎn),任何一個(gè)對(duì)象都可以訪問(wèn)這個(gè)靜態(tài)的值,訪問(wèn)的時(shí)候訪問(wèn)的都是同一塊內(nèi)存。第二點(diǎn),即便是沒(méi)有對(duì)象也可以訪問(wèn)這個(gè)靜態(tài)的值,通過(guò)“類名.靜態(tài)成員變量名”來(lái)訪問(wèn)這個(gè)靜態(tài)的值,所以以后看到某一個(gè)類名加上“.”再加上后面有一個(gè)東西,那么后面這個(gè)東西一定是靜態(tài)的,如”System.out”,這里就是通過(guò)類名(System類)再加上“.”來(lái)訪問(wèn)這個(gè)out的,所以這個(gè)out一定是靜態(tài)的。

再看下面的這段代碼

這段代碼與上一段代碼唯一的區(qū)別是把聲明sid變量的static修飾符給去掉了,此時(shí)的sid就不再是靜態(tài)成員變量,而是非靜態(tài)成員變量了,此時(shí)每一個(gè)new出來(lái)的cat對(duì)象都會(huì)有自己?jiǎn)为?dú)的sid屬性。所以這段代碼執(zhí)行完成后,內(nèi)存中的布局如下圖所示:

由于sid變成了非靜態(tài)成員變量,所以不再有計(jì)數(shù)的功能了。sid與id和name屬性一樣,成為每一個(gè)new出來(lái)的對(duì)象都具有的屬性,所以每一個(gè)new出來(lái)的cat都加上了一個(gè)sid屬性。由于不能再使用”類名.靜態(tài)成員對(duì)象名”的格式訪問(wèn)sid,所以代碼的第一句”Cat.sid =100;”不能這樣使用,否則編譯會(huì)出錯(cuò),必須把這句話注釋掉才能編譯成功。既然無(wú)法訪問(wèn)得到sid的值,所以sid的值就一直都是初始化時(shí)賦給的值0。直到調(diào)用構(gòu)造方法時(shí),執(zhí)行到方法體內(nèi)的代碼id=sid++;時(shí),sid首先把自身的值0賦值給id,所以id的值是0,然后sid自己加1,所以sid變成了1。

所以靜態(tài)變量和非靜態(tài)變量的區(qū)別就在于靜態(tài)變量可以用來(lái)計(jì)數(shù),而非靜態(tài)變量則不行。

理解了內(nèi)存,就理解了一切,就理解了各種各樣的語(yǔ)言。所有的語(yǔ)言無(wú)非都是這樣:局部變量分配內(nèi)存永遠(yuǎn)在棧里面,new出來(lái)的東西分配內(nèi)存永遠(yuǎn)是在堆里,靜態(tài)的東西分配內(nèi)存永遠(yuǎn)是在數(shù)據(jù)區(qū)。剩下的代碼肯定是在代碼區(qū)。所有的語(yǔ)言都是這樣。

在一個(gè)靜態(tài)方法里,如果想訪問(wèn)一個(gè)非靜態(tài)的成員變量,是不能直接訪問(wèn)的,必須在靜態(tài)方法里new一個(gè)對(duì)象出來(lái)才能訪問(wèn)。如果是加了static的成員變量,那么這個(gè)成員變量就是一個(gè)靜態(tài)的成員變量,就可以在main方法里面直接訪問(wèn)了。

main方法是一個(gè)靜態(tài)的方法,main方法要執(zhí)行的時(shí)候不需要new一個(gè)對(duì)象出來(lái)。

動(dòng)態(tài)方法是針對(duì)于某一個(gè)對(duì)象調(diào)用的,靜態(tài)方法不會(huì)針對(duì)某一個(gè)對(duì)象來(lái)調(diào)用,沒(méi)有對(duì)象照樣可以用。所以可以使用”classname.method()”.的形式來(lái)調(diào)用靜態(tài)方法。所以想在main方法里面訪問(wèn)非靜態(tài)成員變量是不可以的,想在main方法里面訪問(wèn)非靜態(tài)方法也是不可以的,因?yàn)榉庆o態(tài)方法只能針對(duì)于某個(gè)對(duì)象來(lái)調(diào)用,沒(méi)有對(duì)象,就找不到方法的執(zhí)行者了。

成員變量只有在new出一個(gè)對(duì)象來(lái)的時(shí)候才在堆內(nèi)存里面分配存儲(chǔ)空間。局部變量在棧內(nèi)存里面分配存儲(chǔ)空間。

靜態(tài)方法不再是針對(duì)某一個(gè)對(duì)象來(lái)調(diào)用,所以不能訪問(wèn)非靜態(tài)的成員。

非靜態(tài)成員專屬于某一個(gè)對(duì)象,想訪問(wèn)非靜態(tài)成員必須new一個(gè)對(duì)象出來(lái)才能訪問(wèn)。

靜態(tài)的變量可以通過(guò)對(duì)象名去訪問(wèn),也可以通過(guò)類名去訪問(wèn),兩者訪問(wèn)的都是同一塊內(nèi)存。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,824評(píng)論 18 399
  • 一:java概述:1,JDK:Java Development Kit,java的開(kāi)發(fā)和運(yùn)行環(huán)境,java的開(kāi)發(fā)工...
    ZaneInTheSun閱讀 2,822評(píng)論 0 11
  • (一)Java部分 1、列舉出JAVA中6個(gè)比較常用的包【天威誠(chéng)信面試題】 【參考答案】 java.lang;ja...
    獨(dú)云閱讀 7,275評(píng)論 0 62
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,872評(píng)論 11 349
  • 我叫林喬巧,今年16歲,身高158,體重,嗯,這個(gè)保密。我為什么叫林喬巧呢?因?yàn)槲野中樟职。?今天是高中報(bào)道的第一...
    俞可閱讀 376評(píng)論 0 1

友情鏈接更多精彩內(nèi)容