Java基礎知識之成員變量和局部變量淺顯易懂總結
引言
成員變量和局部變量在每種編程語言中都有涉及,如果之前了解過其他語言的成員變量或者局部變量,那么在學習java中的成員變量和局部變量時可以看看有那些聯(lián)系和不同,這一塊的東西也不能說難,如果第一次接觸可能會感覺有點亂,所以接下來我先把java中總結的成員變量和局部變量的部分內容先列出來,帶著這些內容學起來會輕松很多!
java變量分類

JVM中的主要內存空間

三大變量內存分配情況

三區(qū)介紹
棧區(qū)
存放各種方法(靜態(tài)方法、實例方法、構造方法等)
ps:局部變量就在這些方法體中;
堆區(qū)
存放new出來的對象(實例);
方法區(qū)
存放各個類,且靜態(tài)變量在此初始化;
基本介紹
成員變量是在 類 中定義的變量
局部變量是在 方法 中定義的變量
成員變量
成員變量分為靜態(tài)變量(類變量) 和 實例變量
靜態(tài)變量有static修飾,它從該類的準備階段就存在了,直到系統(tǒng)銷毀這個類,靜態(tài)變量的作用域與這個類的生存范圍相同;
實例變量沒有static修飾,它從該類的實例被創(chuàng)建時就存在,直到系統(tǒng)銷毀這個實例,實例變量的作用域與對應實例的生存范圍相同;
靜態(tài)變量訪問方法:通過類名訪問,不需要創(chuàng)建實例;
類.靜態(tài)變量
實例變量訪問方法:通過實例訪問,需要先new一個實例
實例.實例變量
其實這里主要注意的還是靜態(tài)變量,主要內容可以看看我的這篇文章:Java中的static———靜態(tài)變量
這里主要說一下成員變量初始化時在內存中運行機制;
先看一個代碼:
public class MemoryShow {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();
Person.name = "李四";
System.out.println("姓名:" + Person.name);
System.out.println("p1年齡:" + p1.age);
System.out.println("p2年齡:" + p2.age);
}
}
class Person {
//靜態(tài)變量
static String name = "張三";
//實例變量
int age;
}
簡單分析一下,當程序第一次執(zhí)行Person類時,系統(tǒng)先加載這個類,并初始化這個類,在類的準備階段,系統(tǒng)就為該類的類變量分配內存空間,并指定默認初始值(靜態(tài)變量name也是在這個階段完成了初始化);
然后接下來系統(tǒng)就在堆內存中為Person類分配了一塊內存區(qū),且為age默認賦值為0;然后生成了Person對象,并通過引用變量p1指向該對象;
當再次執(zhí)行Person類時,已經不需要再為Person類初始化了,所以直接生成了Person對象,通過p2指向它;
局部變量
局部變量相對成員變量就沒有那么復雜了
先分別介紹一下局部變量中的三種不同形式:
形參: 在定義方法簽名時定義的變量,形參的作用域在整個方法內有效
方法局部變量: 在方法體中定義的變量,作用域從定義該變量的地方生效,到該方法結束時失效
代碼塊局部變量: 在代碼塊中定義的變量,作用域從定義該變量的地方生效,到該代碼塊結束時失效
和成員變量不同的一點是:局部變量除了形參外,都需要顯式初始化,就是指定一個初始值,否則無法訪問;
局部變量在內存中的運行機制:
因為局部變量需要顯式初始化,所以系統(tǒng)不會對它進行初始化,即系統(tǒng)并沒有給局部變量分配內存空間,只有它賦值后,系統(tǒng)才會分配內存將該值放入其中;
因為局部變量不屬于任何對象或者類,所以它存放在棧內存中,且棧內存的變量不需要系統(tǒng)垃圾回收,因為它們會隨著方法或者代碼塊運行結束而結束;所以局部變量只保存基本類型或者對象的引用(引用變量),所以局部變量占用內存比較小;
java語法允許局部變量和成員變量重名,但是如果在一個方法里,局部變量會覆蓋成員變量;
如果想要在該方法里訪問成員變量,就需要通過**this引用(針對實例變量)或者類名(針對靜態(tài)變量)**作為調用者來限定訪問成員;
看一個代碼就明白了:
public class RepeatTest {
// 靜態(tài)變量(類變量)
static String name = "張三";
// 實例變量
int age = 18;
public static void main(String[] args) {
// 局部變量 和靜態(tài)變量name = "張三"重名
String name = "李四";
// 因為靜態(tài)變量name被這里的局部變量覆蓋,所以輸出為“李四”
System.out.println("姓名:" + name);
// 這時候如果想要調用靜態(tài)變量可以使用類來調用
//不能用this調用的原因是:main方法是靜態(tài)方法
System.out.println("姓名:" + RepeatTest.name);
// 調用test方法
new RepeatTest().test();
}
public void test() {
// 局部變量 和實例變量age = 18重名
int age = 666;
// 因為實例變量name被這里的局部變量覆蓋,所以輸出為“666”
System.out.println("年齡:" + age);
// 這時候如果想要調用實例變量可以使用this調用
System.out.println("年齡:" + this.age);
}
}
但是,從現(xiàn)在開始就要養(yǎng)成良好的編程習慣,在寫代碼時不要出現(xiàn)局部變量和成員變量重名的情況;
變量使用
說了這么多,可能你已經暈了,但是這些變量歸根結底我們了解它們就是為了用它們,那什么時候用局部變量,什么時候用成員變量呢?
我們先看三個代碼:
public class ScopeTest01 {
//靜態(tài)變量(類成員變量)
//再次強調一下這里為什么定義靜態(tài)變量而不是實例變量
//因為main方法是靜態(tài)方法,不需要對象只通過類調用,而實例變量必須有對象才能調用
static int i;
public static void main(String[] args) {
for (i = 0; i < 5; ++i) {
System.out.println("Hello World!!!");
}
}
}
public class ScopeTest02 {
public static void main(String[] args) {
//局部變量
int i;
for (i = 0; i < 5; ++i) {
System.out.println("Hello World!!!");
}
}
}
public class ScopeTest03 {
public static void main(String[] args) {
// 代碼塊局部變量
for (int i = 0; i < 5; ++i) {
System.out.println("Hello World!!!");
}
}
}
這三個代碼的運行結果都是一樣的,而它們分別用了成員變量和局部變量,結果都一樣,那我們就需要看看那種方法是最好的了;
首先,ScopeTest01 使用的是成員變量,我們都知道成員變量存在于堆內存中,且只有類銷毀時或者實例銷毀時它才銷毀,這就將作用域擴大到類存在范圍或者實例存在范圍,作用域的擴大有兩個壞處:
- 增加了變量的生存時間,會導致更大的內存開銷
- 擴大了變量的作用域,不利于提高程序的內聚性
同理可以對比ScopeTest02 和 ScopeTest03,最后可以總結出 ScopeTest03 最符合規(guī)范;
所以定義變量的時候要盡可能的保證作用范圍最小,這樣可以很好的提高程序的性能,包括局部變量;
考慮使用成員變量有四種情況:
- 如果定義的變量需要描述對象的信息,且每個對象都有可能不同,那么用成員變量中的實例變量;
- 如果定義的變量所描述的信息對這個類的所有對象都相同,那么類相關的信息就定義為成員變量中的靜態(tài)變量;
- 如果某個類中需要一個變量保存該類或者實例運行時的狀態(tài)信息,該變量定義為成員變量;
- 如果某個信息需要在類的多個方法之間共享,則該信息使用成員變量
總結
成員變量和局部變量大概主要內容就是這些了,看完可能還是有點亂,一定要多看幾遍,自己總結一下,這些東西是學習java的基礎內容,這都搞不清的話,那么之后一會一個靜態(tài)變量,一會一個局部變量都把你搞暈了;并且想要用java寫出來好代碼,就必須了解這些內容,這將會在你未來的開發(fā)中起到重要作用;
希望我們一起進步?。。?/p>
ps:內容有問題歡迎私信或者評論區(qū)討論;
到此這篇關于Java基礎知識之成員變量和局部變量淺顯易懂總結的文章就介紹到這了,更多相關Java 成員變量 局部變量內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
spring Retryable注解實現(xiàn)重試詳解
這篇文章主要介紹了spring Retryable注解實現(xiàn)重試詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
PropertiesLoaderUtils 出現(xiàn)中文亂碼的解決方式
這篇文章主要介紹了PropertiesLoaderUtils 出現(xiàn)中文亂碼的解決方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
Spring?Data?Redis切換底層Jedis和Lettuce實現(xiàn)源碼解析
這篇文章主要為大家介紹了Spring?Data?Redis切換底層Jedis和Lettuce實現(xiàn)方法源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11
SpringCloud中Sentinel基礎場景和異常處理方式
這篇文章主要介紹了SpringCloud中Sentinel基礎場景和異常處理方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04

