java變量之成員變量和局部變量以及它們的運行機制

 Java語言根據變量定義位置的不一樣,將變量分爲成員變量和局部變量。成員變量指的是定義在類中(方法外)的變量,局部變量指的是定義在方法中的變量。同時成員變量以是否用static修飾分爲類變量和實例變量。局部變量根據定義位置的不一樣分爲形參,方法局部變量,代碼塊局部變量。如圖1所示。java

 

 

圖1數組

    變量的命名除了應該遵照命名規範之外還應該要見文知意,可以經過名字明白該變量的用途,這樣有利於後續代碼的修改,提升效率。this

    成員變量:成員變量分爲類變量和實例變量,類變量從該類的準備階段開始存在,直至該類被系統銷燬,類變量僅被類所擁有,成員變量不擁有類變量;實例變量則從該類的實例被建立時存在直至實例被銷燬。訪問類變量的方式有兩種:類.類變量和實例.類變量,可是由於實例不擁有類變量,因此其實訪問的仍是類的變量,所以當使用實例對類變量進行修改時,該類變量會受到影響,其餘對象訪問此變量也會看到變化。而訪問實例變量僅有一種方式,實例.實例變量。3d

    局部變量:局部變量分爲形參(整個方法內有效),方法局部變量(從定義開始到方法結束有效),代碼塊局部變量(從定義開始到代碼塊結束有效)。局部變量從被初始化時開始存在直至方法結束。對象

下面將成員變量和臨時變量的初始化和運行機制以例子方式進行說明:blog

    成員變量:生命週期

    我寫了一個Dog類,裏面包含兩個成員變量,類變量nose和實例變量name。如圖2所示。內存

圖2作用域

     在Test類的main方法中,我開始對Dog類進行一系列操做。代碼如圖3所示。io

 

 圖3

    Dog dog = new Dog(),在我進行這一步操做時,若系統第一次使用Dog類,那麼系統須要加載這個類,並初始化類。在類的準備階段,系統爲類分配空間並初始化類變量默認值。如圖4所示。

 

 圖4

     類加載完畢後,系統將建立dog變量,分配內存空間並初始化實例變量,此時堆棧內存狀況如圖5所示。

 

 圖5

     dog.name = 「小黑狗」,執行這句代碼後,我爲dog對象的name變量賦值小黑狗,此時內存狀況如圖6所示。

圖6

    執行Dog dog2 = new Dog();此時系統中已有Dog類,無需再加載Dog類,此時建立Dog對象dog2,系統爲dog2對象分配內存,初始化dog2的name變量爲null。此時內存狀況如圖7所示。

圖7

    dog2.name = 「小白狗」;執行這句代碼爲dog2對象name賦值,狀況與dog1一致。

    dog2.nose = 1,此時雖然經過dog2對象改變了nose的值,可是由於nose屬於類自己,因此類變量nose值被改變,此時用dog1去訪問nose將獲得值1.如圖8所示。

圖8

    綜上所述:java成員變量分爲類變量和實例變量,類變量在類被加載時進行初始化,實例變量在對象實例化時進行初始化,類變量屬於類自己,被全部實例所共享,實例變量屬於實例私有。

    局部變量:局部變量定義以後,必須通過顯示初始化以後才能使用,系統不會爲局部變量執行初始化操做。這意味着定義局部變量以後,系統並未爲這個變量分配內存空間,直到等程序爲這個變量賦初始值時,系統纔會爲局部變量分配內存。局部變量不屬於任何類或實例,它保存在所在方法的內存棧中,若是局部變量時基本類型,則對應內存直接保存值,若爲引用類型,則保存地址,經過該地址引用到該變量實際的對象或數組。

    由於局部變量存在方法棧中,方法結束即被銷燬,因此不須要垃圾回收機制。其生命週期從初始化(不是定義時)開始,到方法結束時被銷燬。

     總結:

     成員變量是無需顯示初始化的,系統在類的準備階段(初始化類變量)或者建立該類的實例時(初始化實例變量)進行默認初始化。而局部變量必須進行顯示初始化,不然不能訪問。

    成員變量和局部變量能夠重名,若重名,在方法中須要訪問成員變量可用this.變量名的方式。(注:this在構造方法中表示當前正在建立的對象,在普通方法中表示調用該方法的對象)。

    根據不一樣變量類型的做用域不一樣,應該合理選擇使用何種變量。好比可使用局部變量的卻使用的成員變量,成員變量存儲在堆中,這就擴大了變量的生存時間和做用域。擴大生存時間致使更大的內存開銷,擴大做用域致使不利於提升程序的內聚性。

 

 

參考--------《java瘋狂講義》

相關文章
相關標籤/搜索