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、變量的使用規則
能不使用成員變量就別使用成員變量
能不使用方法局部變量就別使用方法局部變量
使用代碼塊局部變量性能最好。
