Java基礎(chǔ)知識(shí)之成員變量和局部變量淺顯易懂總結(jié)
引言
成員變量和局部變量在每種編程語言中都有涉及,如果之前了解過其他語言的成員變量或者局部變量,那么在學(xué)習(xí)java中的成員變量和局部變量時(shí)可以看看有那些聯(lián)系和不同,這一塊的東西也不能說難,如果第一次接觸可能會(huì)感覺有點(diǎn)亂,所以接下來我先把java中總結(jié)的成員變量和局部變量的部分內(nèi)容先列出來,帶著這些內(nèi)容學(xué)起來會(huì)輕松很多!
java變量分類
JVM中的主要內(nèi)存空間
三大變量?jī)?nèi)存分配情況
三區(qū)介紹
棧區(qū)
存放各種方法(靜態(tài)方法、實(shí)例方法、構(gòu)造方法等)
ps:局部變量就在這些方法體中;
堆區(qū)
存放new出來的對(duì)象(實(shí)例);
方法區(qū)
存放各個(gè)類,且靜態(tài)變量在此初始化;
基本介紹
成員變量是在 類 中定義的變量
局部變量是在 方法 中定義的變量
成員變量
成員變量分為靜態(tài)變量(類變量) 和 實(shí)例變量
靜態(tài)變量有static修飾,它從該類的準(zhǔn)備階段就存在了,直到系統(tǒng)銷毀這個(gè)類,靜態(tài)變量的作用域與這個(gè)類的生存范圍相同;
實(shí)例變量沒有static修飾,它從該類的實(shí)例被創(chuàng)建時(shí)就存在,直到系統(tǒng)銷毀這個(gè)實(shí)例,實(shí)例變量的作用域與對(duì)應(yīng)實(shí)例的生存范圍相同;
靜態(tài)變量訪問方法:通過類名訪問,不需要?jiǎng)?chuàng)建實(shí)例;
類.靜態(tài)變量
實(shí)例變量訪問方法:通過實(shí)例訪問,需要先new一個(gè)實(shí)例
實(shí)例.實(shí)例變量
其實(shí)這里主要注意的還是靜態(tài)變量,主要內(nèi)容可以看看我的這篇文章:Java中的static———靜態(tài)變量
這里主要說一下成員變量初始化時(shí)在內(nèi)存中運(yùn)行機(jī)制;
先看一個(gè)代碼:
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 = "張三"; //實(shí)例變量 int age; }
簡(jiǎn)單分析一下,當(dāng)程序第一次執(zhí)行Person類時(shí),系統(tǒng)先加載這個(gè)類,并初始化這個(gè)類,在類的準(zhǔn)備階段,系統(tǒng)就為該類的類變量分配內(nèi)存空間,并指定默認(rèn)初始值(靜態(tài)變量name也是在這個(gè)階段完成了初始化);
然后接下來系統(tǒng)就在堆內(nèi)存中為Person類分配了一塊內(nèi)存區(qū),且為age默認(rèn)賦值為0;然后生成了Person對(duì)象,并通過引用變量p1指向該對(duì)象;
當(dāng)再次執(zhí)行Person類時(shí),已經(jīng)不需要再為Person類初始化了,所以直接生成了Person對(duì)象,通過p2指向它;
局部變量
局部變量相對(duì)成員變量就沒有那么復(fù)雜了
先分別介紹一下局部變量中的三種不同形式:
形參: 在定義方法簽名時(shí)定義的變量,形參的作用域在整個(gè)方法內(nèi)有效
方法局部變量: 在方法體中定義的變量,作用域從定義該變量的地方生效,到該方法結(jié)束時(shí)失效
代碼塊局部變量: 在代碼塊中定義的變量,作用域從定義該變量的地方生效,到該代碼塊結(jié)束時(shí)失效
和成員變量不同的一點(diǎn)是:局部變量除了形參外,都需要顯式初始化,就是指定一個(gè)初始值,否則無法訪問;
局部變量在內(nèi)存中的運(yùn)行機(jī)制:
因?yàn)榫植孔兞啃枰@式初始化,所以系統(tǒng)不會(huì)對(duì)它進(jìn)行初始化,即系統(tǒng)并沒有給局部變量分配內(nèi)存空間,只有它賦值后,系統(tǒng)才會(huì)分配內(nèi)存將該值放入其中;
因?yàn)榫植孔兞坎粚儆谌魏螌?duì)象或者類,所以它存放在棧內(nèi)存中,且棧內(nèi)存的變量不需要系統(tǒng)垃圾回收,因?yàn)樗鼈儠?huì)隨著方法或者代碼塊運(yùn)行結(jié)束而結(jié)束;所以局部變量只保存基本類型或者對(duì)象的引用(引用變量),所以局部變量占用內(nèi)存比較??;
java語法允許局部變量和成員變量重名,但是如果在一個(gè)方法里,局部變量會(huì)覆蓋成員變量;
如果想要在該方法里訪問成員變量,就需要通過**this引用(針對(duì)實(shí)例變量)或者類名(針對(duì)靜態(tài)變量)**作為調(diào)用者來限定訪問成員;
看一個(gè)代碼就明白了:
public class RepeatTest { // 靜態(tài)變量(類變量) static String name = "張三"; // 實(shí)例變量 int age = 18; public static void main(String[] args) { // 局部變量 和靜態(tài)變量name = "張三"重名 String name = "李四"; // 因?yàn)殪o態(tài)變量name被這里的局部變量覆蓋,所以輸出為“李四” System.out.println("姓名:" + name); // 這時(shí)候如果想要調(diào)用靜態(tài)變量可以使用類來調(diào)用 //不能用this調(diào)用的原因是:main方法是靜態(tài)方法 System.out.println("姓名:" + RepeatTest.name); // 調(diào)用test方法 new RepeatTest().test(); } public void test() { // 局部變量 和實(shí)例變量age = 18重名 int age = 666; // 因?yàn)閷?shí)例變量name被這里的局部變量覆蓋,所以輸出為“666” System.out.println("年齡:" + age); // 這時(shí)候如果想要調(diào)用實(shí)例變量可以使用this調(diào)用 System.out.println("年齡:" + this.age); } }
但是,從現(xiàn)在開始就要養(yǎng)成良好的編程習(xí)慣,在寫代碼時(shí)不要出現(xiàn)局部變量和成員變量重名的情況;
變量使用
說了這么多,可能你已經(jīng)暈了,但是這些變量歸根結(jié)底我們了解它們就是為了用它們,那什么時(shí)候用局部變量,什么時(shí)候用成員變量呢?
我們先看三個(gè)代碼:
public class ScopeTest01 { //靜態(tài)變量(類成員變量) //再次強(qiáng)調(diào)一下這里為什么定義靜態(tài)變量而不是實(shí)例變量 //因?yàn)閙ain方法是靜態(tài)方法,不需要對(duì)象只通過類調(diào)用,而實(shí)例變量必須有對(duì)象才能調(diào)用 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!!!"); } } }
這三個(gè)代碼的運(yùn)行結(jié)果都是一樣的,而它們分別用了成員變量和局部變量,結(jié)果都一樣,那我們就需要看看那種方法是最好的了;
首先,ScopeTest01 使用的是成員變量,我們都知道成員變量存在于堆內(nèi)存中,且只有類銷毀時(shí)或者實(shí)例銷毀時(shí)它才銷毀,這就將作用域擴(kuò)大到類存在范圍或者實(shí)例存在范圍,作用域的擴(kuò)大有兩個(gè)壞處:
- 增加了變量的生存時(shí)間,會(huì)導(dǎo)致更大的內(nèi)存開銷
- 擴(kuò)大了變量的作用域,不利于提高程序的內(nèi)聚性
同理可以對(duì)比ScopeTest02 和 ScopeTest03,最后可以總結(jié)出 ScopeTest03 最符合規(guī)范;
所以定義變量的時(shí)候要盡可能的保證作用范圍最小,這樣可以很好的提高程序的性能,包括局部變量;
考慮使用成員變量有四種情況:
- 如果定義的變量需要描述對(duì)象的信息,且每個(gè)對(duì)象都有可能不同,那么用成員變量中的實(shí)例變量;
- 如果定義的變量所描述的信息對(duì)這個(gè)類的所有對(duì)象都相同,那么類相關(guān)的信息就定義為成員變量中的靜態(tài)變量;
- 如果某個(gè)類中需要一個(gè)變量保存該類或者實(shí)例運(yùn)行時(shí)的狀態(tài)信息,該變量定義為成員變量;
- 如果某個(gè)信息需要在類的多個(gè)方法之間共享,則該信息使用成員變量
總結(jié)
成員變量和局部變量大概主要內(nèi)容就是這些了,看完可能還是有點(diǎn)亂,一定要多看幾遍,自己總結(jié)一下,這些東西是學(xué)習(xí)java的基礎(chǔ)內(nèi)容,這都搞不清的話,那么之后一會(huì)一個(gè)靜態(tài)變量,一會(huì)一個(gè)局部變量都把你搞暈了;并且想要用java寫出來好代碼,就必須了解這些內(nèi)容,這將會(huì)在你未來的開發(fā)中起到重要作用;
希望我們一起進(jìn)步?。。?/p>
ps:內(nèi)容有問題歡迎私信或者評(píng)論區(qū)討論;
到此這篇關(guān)于Java基礎(chǔ)知識(shí)之成員變量和局部變量淺顯易懂總結(jié)的文章就介紹到這了,更多相關(guān)Java 成員變量 局部變量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA三種攔截方式詳解(原生過濾器Filter、springMVC攔截器、aop切面)
在Java開發(fā)中方法攔截是一種常見的技術(shù),可以用于在方法執(zhí)行前后添加額外的邏輯或修改方法的行為,這篇文章主要給大家介紹了關(guān)于JAVA三種攔截方式的相關(guān)資料,文中介紹的方式分別是原生過濾器Filter、springMVC攔截器、aop切面,需要的朋友可以參考下2024-05-05java后端返回?cái)?shù)據(jù)給前端時(shí)去除值為空或NULL的屬性、忽略某些屬性代碼示例
在Java開發(fā)中我們處理JSON數(shù)據(jù)時(shí)經(jīng)常會(huì)遇到空值(null)的情況,這篇文章主要給大家介紹了關(guān)于java后端返回?cái)?shù)據(jù)給前端時(shí)去除值為空或NULL的屬性、忽略某些屬性的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07SpringCloud負(fù)載均衡實(shí)現(xiàn)定向路由詳情
這篇文章主要介紹了SpringCloud負(fù)載均衡實(shí)現(xiàn)定向路由詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08關(guān)于springboot 中使用httpclient或RestTemplate做MultipartFile文件跨服務(wù)傳輸
這篇文章主要介紹了關(guān)于springboot 中使用httpclient或RestTemplate做MultipartFile文件跨服務(wù)傳輸?shù)膯栴},本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01Java實(shí)現(xiàn)用戶不可重復(fù)登錄功能
這篇文章主要介紹了Java實(shí)現(xiàn)用戶不可重復(fù)登錄功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2016-12-12Spring MVC 4.1.3 + MyBatis零基礎(chǔ)搭建Web開發(fā)框架(注解模式)
本篇文章主要介紹了Spring MVC 4.1.3 + MyBatis零基礎(chǔ)搭建Web開發(fā)框架(注解模式),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03