關於java成員變數和區域性變數
1、成員變數和區域性變數簡述
在Java語言裡,根據定義變數位置的不同,可以將變數分成兩大類:成員變數和區域性變數。二者的執行機制存在較大差異。
1.1成員變數
類變數從該類的準備階段起開始存在,直到系統完全銷燬這個類,類變數的作用域與這個類的生存範圍相同;
而例項變數則從該類的例項被建立起開始存在,直到系統完全銷燬這個例項,例項變數的作用域與對應例項的生存範圍相同。
正是基於這個原因,可以把類變數和例項變數統稱為成員變數。其中類變數可以理解為類成員變數,它作為類本身的一個成員,與類本身共存亡;例項變數則可以理解為例項成員變數,它作為例項的一個成員與例項共存亡。
只要類存在,類就可以訪問類變數 類.類變數
只要例項存在,例項就可以訪問例項變數 例項.例項變數
當然例項也可以訪問類變數。但是需要注意的是因為例項不擁有類變數,所以通過例項來訪問類變數進行操作,實際上是對類變數進行操作 ,當有其他例項來訪問類變數時,訪問的類變數是被物件訪問操作過的類變數。
成員變數無需顯示初始化,只要為一個類定義了類變數或例項變數,系統就會在這個類的準備階段或建立該類的例項時進行預設初始化。
1.2區域性變數
區域性變數根據定義形式的不同,又可以分為如下三種:
形參:在定義方法簽名時定義的變數,形參的作用域在整個方法中都有效
方法區域性變數:在方法體內定義的區域性變數,它的作用域是從定義該變數的地方生效,到該方法結束時失效
程式碼塊區域性變數:這個區域性變數的作用域從定義該變數的地方生效,到該程式碼結束時失效。
一個變數只在一對{}中起作用。。
java允許區域性變數和成員變數同名,如果方法中區域性變數和成員變數同名,區域性變數就會覆蓋成員變數,如果需要在這個方法中引用被覆蓋成員變數,則可使用this(對於例項變數)或類名(對於類變數)作為呼叫者來限定訪問成員變數。
2、成員變數的初始化和記憶體中的執行機制
接下來以下面程式碼來舉例說明成員變數的初始化和記憶體中的執行機制
1 public class Person { 2 public int num; 3 public String name; 4 5 public static void main(String[] args) { 6 Person p1 = new Person(); 7 Person p2 = new Person(); 8 p1.num = 2; 9 p2.num = 3; 10 p1.name = "張三"; 11 p2.name = "李四"; 12 } 13 14 15 }
當程式執行Person p1 = new Person();時,如果這行程式碼是第一次使用Person類,則系統通常會在第一次使用Person類時載入這個類,並初始化這個類,在類的準備 階段,系統將會為該類的類變數分配記憶體空間,並指定預設初始值。當person類初始化完成後,系統記憶體中的儲存示意圖如下圖所示。
可以看出,當person類初始化完成後,系統將在堆記憶體中為Person分配一塊記憶體空間,實際上是建立了一個類物件,在這塊記憶體區裡包含了儲存num類變數的記憶體,並設定num的預設初始值為0。
系統接著建立了一個Person物件,並把這個Person物件賦給p1變數,Person物件包含了名為name的例項變數,例項變數是在建立例項時分配記憶體空間並指定初始值的。當建立了第一個person物件後,系統記憶體中的儲存示意圖如下圖所示。
從上圖可以看出num不屬於物件,它屬於類,所以建立第一個物件時並不需要為num分配記憶體空間,系統只是為name分配了記憶體空間,並指定初始值為null。
建立第二個物件p2時,由於在建立第一個物件時已經對類進行了初始化,所以在建立p2時對類進行初始化,物件的建立過程與第一個物件的建立過程沒有什麼區別。
第二個物件建立完成後,成員變數如上圖所示在記憶體中儲存。
**當程式需要訪問類變數時,儘量使用類來作為主調,不要使用物件作為主調,這個可以避免產生歧義。
3、區域性變數的初始化和記憶體中的執行機制
*區域性變數必須經過顯示初始化之後才能使用,系統不會為區域性變數執行初始化。定義了局部變數以後,系統並沒有給區域性變數進行初始化,直到程式給這個區域性變數賦給初值時,系統才會為這個區域性變數分配記憶體空間,並將初始值儲存到這塊記憶體中。
*區域性變數不屬於任何類或者例項,因此它總是儲存在方法的棧記憶體中。如果區域性變數是基本資料型別,則該變數直接儲存在方法的棧記憶體中,如果是引用變數則將引用的地址儲存在方法的棧記憶體中。
*棧記憶體中的變數無需系統垃圾回收,隨著方法或者程式碼塊的執行結束而結束。區域性變數通常只儲存了具體的值或者引用地址,所以所佔的記憶體比較小。
4、變數的使用規則
能不使用成員變數就別使用成員變數
能不使用方法區域性變數就別使用方法區域性變數
使用程式碼塊區域性變數效能最好。