標籤:
java局部變數與成員變數相關問題總結 2013-02-03 12:39 156人閱讀 評論(0) 收藏 舉報
一、Java中的所有變數可以分成局部變數和成員變數。他們的區別:
1. 定義
成員變數:在類體裡面定義的變數稱為成員變數;
局部變數:形參、方法、代碼塊中定義的變數,都屬於局部變數。
(註:局部變數定義必須在方法裡面!)
2. 詳細分類
成員變數:1)類變數(靜態變數)——有static修飾;
2)執行個體變數(非靜態變數)——沒有static修飾。
局部變數:1)形參——方法簽名中定義的變數;
2)方法局部變數——在方法(函數)內定義;
3)代碼塊局部變數——在代碼塊內定義(例如for迴圈裡面的變數)。
3. 初始化
成員變數:無需顯式初始化,只要為一個類定義了類變數或執行個體變數,則系統會在這
個類的準備階段或建立這個類的執行個體時進行預設初始化。
局部變數:除了形參之外,都必須顯式初始化。
4. 作用範圍
成員變數:作用於整個類中;
局部變數:作用於方法(函數)中,或者語句中。
5. 在記憶體中的位置
成員變數:在堆記憶體中。因為類或對象的存在,才在記憶體中存在;
局部變數:在棧記憶體中。因為他不屬於任何類或執行個體,因此他總是儲存在其所在方法的棧記憶體中的。如果局部變數是基本類型的變數,則直接把這個變數的值儲存在該變數對應的記憶體中;如果是參考型別的變數,則這個變數存放的是地址,通過該地址引用到該變數實際引用的對象或數組。
二、類變數和執行個體變數的區別:
1. 引用
類變數:可以向前引用;
執行個體變數:不可以向前引用,如果向前引用,則成為非法向前引用。
2. 歸屬及生命週期
類變數:屬於類本身。可以理解為類成員變數。它作為類的一個成員,與類共存亡;
執行個體變數:屬於類的執行個體對象。可以理解為執行個體成員變數。它作為執行個體的一個成員,
與執行個體共存亡。
3. 空間分配
類變數:不依賴類的執行個體,只在初始化時在棧記憶體中被分配一次空間。無論類的執行個體
被建立幾次,都不再為類變數分配空間;
執行個體變數:在建立執行個體時分配記憶體空間
4. 存放位置
類變數:隨著類的載入而存在於方法區中;
執行個體變數:隨著對象的建立而存在於堆記憶體中。
範例程式碼如下:
[java] view plaincopyprint?
- class Person
- {
- String name;//執行個體變數
- static String country = "CN";//類變數
-
- public static void country()//靜態成員函數
- {
- System.out.println("my country is " + country);
- }
-
- public void shout()
- {
- System.out.println("my name is " + name);
- }
-
- public void calculation(int num)//num為形參
- {
- int sum = 0;//sum為方法局部變數
-
- for(int i=0;i<=num;i++)//i為代碼塊局部變數
- {
- sum = sum + i;
- }
-
- System.out.println("the result is " + sum);
- }
- }
-
- class StaticDemo
- {
- public static void main(String[] args)
- {
- Person.country();//類可以直接存取類變數
- Person p = new Person();
- p.name = "zhagnsan";
- p.shout();
- p.calculation(100);
- }
- }
class Person{String name;//執行個體變數static String country = "CN";//類變數public static void country()//靜態成員函數{System.out.println("my country is " + country);}public void shout(){System.out.println("my name is " + name);}public void calculation(int num)//num為形參{int sum = 0;//sum為方法局部變數for(int i=0;i<=num;i++)//i為代碼塊局部變數{sum = sum + i;}System.out.println("the result is " + sum);}}class StaticDemo {public static void main(String[] args) {Person.country();//類可以直接存取類變數Person p = new Person();p.name = "zhagnsan";p.shout();p.calculation(100);}}
三、各變數的一些要點:
1. 成員變數的初始化和在記憶體中的運行機制:在類的準備階段,系統將會為該類的類變數分配記憶體空間(堆記憶體),並制定預設初始值。初始化完成後,會在堆記憶體中分
配一塊記憶體區。
2. 成員變數的考慮使用情形:
1)描述某個對象的固有資訊的變數,例如人的身高;
2)儲存某個類,或某個執行個體狀態資訊的變數;
3)如果某個資訊需要在某個類的多個方法之間進行共用,則這個資訊應該使用成員變數。
3. 當成員變數的範圍擴大到類存在範圍或者對象存在範圍,這種範圍的擴大有兩個害處:
1)增大了變數的存留時間,這將導致更大的系統開銷;
2)擴大了變數的範圍,這不利於提高程式的內聚性。
4.java允許局部變數和成員變數同名,如果方法裡的局部變數和成員變數同名,那麼局部變數會覆蓋成員變數,如果需要在這個方法裡使用成員變數,那麼需要this(對於
執行個體屬性)或類名(對於類屬性)作為調用者來限定訪問這個成員變數。
5. 類變數也可以用該類的執行個體來訪問:執行個體.類變數。 (這其實是一個假象,其實是類.類變數這樣來訪問) 也就是說,如果通過一個執行個體修改了類變數的值,由於這個類
變數並不屬於它,而是屬於它對應的類。因此,修改的依然是類的類變數,與通過該類來修改類變數的結果完全相同,這樣導致該類的其他執行個體在訪問這個類變數時也將獲
得這個被修改過的值。
6. 三種局部變數的範圍:
1)形參:在整個方法內有效;
2)方法局部變數:從定義該變數的地方生效,到該方法結束時失效;
3)代碼塊局部變數:從定義該變數的地方生效,到該代碼塊結束時失效。
7. 在java中,一個方法裡面不能定義兩個同名的局部變數,即使一個是方法變數,一個是代碼塊變數或者形參也不行。
8. 形參的初始化過程:當通過類或對象調用某個方法時,系統會在該方法區內為所有形參分配記憶體空間,並將實參的值賦給對應的形參,這就完成了形參的初始化。
9. 成員變數在堆記憶體中,因為對象的存在,才在記憶體中存在;而局部變數存在於棧記憶體中;成員函數不在堆記憶體中,而是在java的方法區中,成員函數的局部變數在堆記憶體中。
四、棧記憶體和堆記憶體小結:
1. 棧記憶體:某一個函數被調用時,這個函數會在棧記憶體裡面申請一片空間,以後在這個函數內部定義的變數,都會分配到這個函數所申請到的棧。當函數運行結束時,分配給函數的棧空間被收回,在這個函數中被定義的變數也隨之被釋放和消失。
2. 堆記憶體:通過new產生的數組和對象分配在堆記憶體中。堆記憶體中分配的記憶體,由JVM提供的GC(記憶體回收機制)來管理。在堆記憶體中產生了一個數組對象後,我們還可以在棧中定義一個變數,這個棧中變數的取值等於堆中對象的首地址。棧記憶體中的變數就成了堆記憶體中數組或者對象的引用變數。我們以後就可以在程式中直接使用棧中的這個變數來訪問我們在堆中分配的數組或者對象,引用變數相當於數組或者對象起的一個別名,或者代號。
五、引用變數:
引用變數是一個普通的變數,定義時在棧中分配;引用變數在被運行到它的範圍之外時就被釋放,而我們的數組和對象本身是在堆中分配的,即使程式運行到使用new產生對象的語句所在的函數或者代碼之後,我們剛才被產生的數組和對象也不會被釋放。數組和對象只是在沒有引用變數指向它,也就是沒有任何引用變數的值等於它的首地址,它才會變成垃圾不會被使用,但是它任然佔據著記憶體空間不放(這也就是我們Java比較吃記憶體的一個原因),在隨後一個不確定的時間被記憶體回收行程收走。
} public void calculation(int num)//num為形參 { int sum = 0;//sum為方法局部變數 for(int i=0;i<=num;i++)//i為代碼塊局部變數 { sum = sum + i; } System.out.println("the result is " + sum); } } class StaticDemo { public static void main(String[] args) { Person.country();//類可以直接存取類變數 Person p = new Person(); p.name = "zhagnsan"; p.shout(); p.calculation(100); } }
三、各變數的一些要點:
1. 成員變數的初始化和在記憶體中的運行機制:在類的準備階段,系統將會為該類的類變數分配記憶體空間(堆記憶體),並制定預設初始值。初始化完成後,會在堆記憶體中分
配一塊記憶體區。
2. 成員變數的考慮使用情形:
1)描述某個對象的固有資訊的變數,例如人的身高;
2)儲存某個類,或某個執行個體狀態資訊的變數;
3)如果某個資訊需要在某個類的多個方法之間進行共用,則這個資訊應該使用成員變數。
3. 當成員變數的範圍擴大到類存在範圍或者對象存在範圍,這種範圍的擴大有兩個害處:
1)增大了變數的存留時間,這將導致更大的系統開銷;
2)擴大了變數的範圍,這不利於提高程式的內聚性。
4.java允許局部變數和成員變數同名,如果方法裡的局部變數和成員變數同名,那麼局部變數會覆蓋成員變數,如果需要在這個方法裡使用成員變數,那麼需要this(對於
執行個體屬性)或類名(對於類屬性)作為調用者來限定訪問這個成員變數。
5. 類變數也可以用該類的執行個體來訪問:執行個體.類變數。 (這其實是一個假象,其實是類.類變數這樣來訪問) 也就是說,如果通過一個執行個體修改了類變數的值,由於這個類
變數並不屬於它,而是屬於它對應的類。因此,修改的依然是類的類變數,與通過該類來修改類變數的結果完全相同,這樣導致該類的其他執行個體在訪問這個類變數時也將獲
得這個被修改過的值。
6. 三種局部變數的範圍:
1)形參:在整個方法內有效;
2)方法局部變數:從定義該變數的地方生效,到該方法結束時失效;
3)代碼塊局部變數:從定義該變數的地方生效,到該代碼塊結束時失效。
7. 在java中,一個方法裡面不能定義兩個同名的局部變數,即使一個是方法變數,一個是代碼塊變數或者形參也不行。
8. 形參的初始化過程:當通過類或對象調用某個方法時,系統會在該方法區內為所有形參分配記憶體空間,並將實參的值賦給對應的形參,這就完成了形參的初始化。
9. 成員變數在堆記憶體中,因為對象的存在,才在記憶體中存在;而局部變數存在於棧記憶體中;成員函數不在堆記憶體中,而是在java的方法區中,成員函數的局部變數在堆記憶體中。
四、棧記憶體和堆記憶體小結:
1. 棧記憶體:某一個函數被調用時,這個函數會在棧記憶體裡面申請一片空間,以後在這個函數內部定義的變數,都會分配到這個函數所申請到的棧。當函數運行結束時,分配給函數的棧空間被收回,在這個函數中被定義的變數也隨之被釋放和消失。
2. 堆記憶體:通過new產生的數組和對象分配在堆記憶體中。堆記憶體中分配的記憶體,由JVM提供的GC(記憶體回收機制)來管理。在堆記憶體中產生了一個數組對象後,我們還可以在棧中定義一個變數,這個棧中變數的取值等於堆中對象的首地址。棧記憶體中的變數就成了堆記憶體中數組或者對象的引用變數。我們以後就可以在程式中直接使用棧中的這個變數來訪問我們在堆中分配的數組或者對象,引用變數相當於數組或者對象起的一個別名,或者代號。
五、引用變數:
引用變數是一個普通的變數,定義時在棧中分配;引用變數在被運行到它的範圍之外時就被釋放,而我們的數組和對象本身是在堆中分配的,即使程式運行到使用new產生對象的語句所在的函數或者代碼之後,我們剛才被產生的數組和對象也不會被釋放。數組和對象只是在沒有引用變數指向它,也就是沒有任何引用變數的值等於它的首地址,它才會變成垃圾不會被使用,但是它任然佔據著記憶體空間不放(這也就是我們Java比較吃記憶體的一個原因),在隨後一個不確定的時間被記憶體回收行程收走。
java局部變數與成員變數相關問題總結