變量種類:
- 全局變量(成員變量)
- 局部變量
- 靜態(tài)變量
變量解釋
1. 全局變量(成員變量):
1.全局變量定義在類中,在整個類中都可以被訪問
2.全局變量有默認(rèn)的初始化值
3.全局變量隨著對象的建立而建立,隨著對象的消失而消失礁阁,存在于對象所在的堆內(nèi)存中
2. 局部變量:
1.局部變量定義在局部范圍內(nèi):如方法独悴,函數(shù)碗淌,語句中算灸,只在作用域有效
2.局部變量沒有默認(rèn)初始化值
3.局部變量存在于棧內(nèi)存中,作用的范圍結(jié)束往枷,變量空間會自動釋放
3. 靜態(tài)變量:
用static關(guān)鍵字修飾的變量,被所有對象所共享
全局變量(成員變量)與靜態(tài)變量的區(qū)別:
- 生命周期不同
- 全局變量隨對象創(chuàng)建而創(chuàng)建凄杯,隨對象銷毀而銷毀
- 靜態(tài)變量隨類加載而加載错洁,隨類消失而消失
- 調(diào)用方式不同
- 全局變量只能被對象調(diào)用
- 靜態(tài)變量可以被對象調(diào)用,也可以被類名調(diào)用
- 別名不同
- 全局變量也稱為實例變量戒突。
- 靜態(tài)變量也稱為類變量屯碴。
- 數(shù)據(jù)存儲位置不同
- 全局變量存儲在堆內(nèi)存的對象中,所以也叫對象的特有數(shù)據(jù)膊存。
- 靜態(tài)變量數(shù)據(jù)存儲在方法區(qū)(共享數(shù)據(jù)區(qū))的靜態(tài)區(qū)导而,所以也叫對象的共享數(shù)據(jù)。
差異對比:
基本數(shù)據(jù)類型(8個):
int,byte,char,short,float,double,long,boolean
包裝類數(shù)據(jù)(8個):
Integer,Byte,Character,Short,Float,Double,Long,Boolean
java中的數(shù)據(jù)存儲:
- 寄存器(register)隔崎。 這是最快的存儲區(qū)今艺,因為它位于不同于其他存儲區(qū)的地方——處理器內(nèi)部。但是寄存器的數(shù)量極其有限爵卒,所以寄存器由編譯器根據(jù)需求進(jìn)行分配虚缎。你不能直接控制,也不能在程序中感覺到寄存器存在的任何跡象钓株。
------最快的存儲區(qū), 由編譯器根據(jù)需求進(jìn)行分配,我們在程序中無法控制
- 棧(stack)实牡。位于通用RAM中陌僵,但通過它的“堆棧指針”可以從處理器哪里獲得支持。堆棧指針若向下移動创坞,則分配新的內(nèi)存拾弃;若向上移動,則釋放那些 內(nèi)存摆霉。這是一種快速有效的分配存儲方法豪椿,僅次于寄存器。創(chuàng)建程序時候携栋,JAVA編譯器必須知道存儲在堆棧內(nèi)所有數(shù)據(jù)的確切大小和生命周期搭盾,因為它必須生成 相應(yīng)的代碼,以便上下移動堆棧指針婉支。這一約束限制了程序的靈活性鸯隅,所以雖然某些JAVA數(shù)據(jù)存儲在堆棧中——特別是對象引用,但是JAVA對象不存儲其 中向挖。
------存放基本類型的變量數(shù)據(jù)和對象蝌以,數(shù)組的引用,但對象本身不存放在棧中何之,而是存放在堆(new 出來的對象)或者常量池中(字符串常量對象存放在常量池中)
- 堆(heap)跟畅。一種通用性的內(nèi)存池(也存在于RAM中),用于存放所有的JAVA對象溶推。堆不同于堆棧的好處是:編譯器不需要知道要從堆里分配多少存儲區(qū)域徊件,也不必知道存儲的數(shù)據(jù)在堆里存活多長時間。因此蒜危,在堆里分配存儲有很大的靈活性虱痕。當(dāng)你需要創(chuàng)建一個對象的時候,只需要new寫一行簡單的代碼辐赞,當(dāng)執(zhí)行這行代碼時部翘,會自動在堆里進(jìn)行存儲分配。當(dāng)然响委,為這種靈活性必須要付出相應(yīng)的代價新思,用堆進(jìn)行存儲分配比用堆棧進(jìn)行存儲存儲需要更多的時間。
------存放所有new出來的對象晃酒。
- 靜態(tài)存儲(static storage)表牢。這里的“靜態(tài)”是指“在固定的位置”。靜態(tài)存儲里存放程序運行時一直存在的數(shù)據(jù)贝次。你可用關(guān)鍵字static來標(biāo)識一個對象的特定元素是靜態(tài)的崔兴,但JAVA對象本身從來不會存放在靜態(tài)存儲空間里。
------存放靜態(tài)成員(static定義的)
- 常量存儲(constant storage)。常量值通常直接存放在程序代碼內(nèi)部敲茄,這樣做是安全的位谋,因為它們永遠(yuǎn)不會被改變。有時堰燎,在嵌入式系統(tǒng)中掏父,常量本身會和其他部分分割離開,所以在這種情況下秆剪,可以選擇將其放在ROM中
------存放字符串常量和基本類型常量(public static final)
- 非RAM存儲赊淑。如果數(shù)據(jù)完全存活于程序之外,那么它可以不受程序的任何控制仅讽,在程序沒有運行時也可以存在陶缺。
------硬盤等永久存儲空間
就速度來說,有如下關(guān)系:
寄存器 > 棧 > 堆 > 其它
這里我們主要關(guān)心棧洁灵,堆和常量池饱岸,對于棧和常量池中的對象可以共享,對于堆中的對象不可以共享徽千。
棧中的數(shù)據(jù)大小和生命周期是可以確定的苫费,當(dāng)沒有引用指向數(shù)據(jù)時,這個數(shù)據(jù)就會消失双抽。堆中的對象的由垃圾回收器負(fù)責(zé)回收百框,因此大小和生命周期不需要確定,具有很大的靈活性荠诬。
棧內(nèi)存:
某一個函數(shù)被調(diào)用時琅翻,這個函數(shù)會在棧內(nèi)存里面申請一片空間,以后在這個函數(shù)內(nèi)部定義的變量柑贞,都會分配到這個函數(shù)所申請到的棧。當(dāng)函數(shù)運行結(jié)束時聂抢,分配給函數(shù)的椌唬空間被收回,在這個函數(shù)中被定義的變量也隨之被釋放和消失琳疏。棧內(nèi)存比堆內(nèi)存小得多
堆內(nèi)存:
通過new產(chǎn)生的數(shù)組和對象分配在堆內(nèi)存中有决。堆內(nèi)存中分配的內(nèi)存,由JVM提供的GC(垃圾回收機(jī)制)來管理空盼。在堆內(nèi)存中產(chǎn)生了一個數(shù)組對象后书幕,我們還可以在棧中定義一個變量,這個棧中變量的取值等于堆中對象的首地址揽趾。棧內(nèi)存中的變量就成了堆內(nèi)存中數(shù)組或者對象的引用變量台汇。我們以后就可以在程序中直接使用棧中的這個變量來訪問我們在堆中分配的數(shù)組或者對象,引用變量相當(dāng)于數(shù)組或者對象起的一個別名,或者代號苟呐。
引用變量是一個普通的變量痒芝,定義時在棧中分配;引用變量在被運行到它的作用域之外時就被釋放牵素,而我們的數(shù)組和對象本身是在堆中分配的严衬,即使程序運行到使用new產(chǎn)生對象的語句所在的函數(shù)或者代碼之后,我們剛才被產(chǎn)生的數(shù)組和對象也不會被釋放笆呆。數(shù)組和對象只是在沒有引用變量指向它请琳,也就是沒有任何引用變量的值等于它的首地址,它才會變成垃圾不會被使用赠幕,但是它任然占據(jù)著內(nèi)存空間不放(這也就是我們Java比較吃內(nèi)存的一個原因)单起,在隨后一個不確定的時間被垃圾回收器收走。
堆內(nèi)存和棧內(nèi)存的區(qū)別
1劣坊、應(yīng)用程序所有的部分都使用堆內(nèi)存嘀倒,然后棧內(nèi)存通過一個線程運行來使用。
2局冰、不論對象什么時候創(chuàng)建测蘑,他都會存儲在堆內(nèi)存中,棧內(nèi)存包含它的引用康二。棧內(nèi)存只包含原始值變量和堆中對象變量的引用碳胳。
3、存儲在堆中的對象是全局可以被訪問的沫勿,然而棧內(nèi)存不能被其他線程所訪問挨约。
4、棧中的內(nèi)存管理使用LIFO的方式完成产雹,而堆內(nèi)存的管理要更復(fù)雜了诫惭,因為它是全局被訪問的。堆內(nèi)存被分為蔓挖,年輕一代夕土,老一代等等(Young Generation and Old Generation.)。
5瘟判、棧內(nèi)存是生命周期很短的怨绣,然而堆內(nèi)存的生命周期從程序的運行開始到運行結(jié)束。
6拷获、我們可以使用-Xms和-Xmx JVM選項定義開始的大小和堆內(nèi)存的最大值篮撑,我們可以使用-Xss定義棧的大小
7、當(dāng)棧內(nèi)存滿的時候匆瓜,Java拋出java.lang.StackOverFlowError異常而堆內(nèi)存滿的時候拋出java.lang.OutOfMemoryError: Java Heap Space錯誤
8赢笨、和堆內(nèi)存比未蝌,棧內(nèi)存要小的多,因為明確使用了內(nèi)存分配規(guī)則(LIFO)质欲,和堆內(nèi)存相比棧內(nèi)存非呈鞑海快。
例(引用):
String 類型的變量通常有兩種賦值方式:一種直接賦值嘶伟,例如String a = "hello world"怎憋;另一種是用構(gòu)造方法,例如 String b = new String ("hello world");那么這里的a 和b是否相等呢九昧?他們又有什么不同 呢绊袋?
如果用=作比較,則它們不相等铸鹰,因為“=”比較的是基本數(shù)據(jù)類型的值是否相等或者比較對象是否為同一個對象癌别;而變量a和變量b指向的是兩個不同的對象,為什么這么說呢蹋笼?先來理解一下2個變量的賦值過程展姐,對于表達(dá)式String a = "hello world",會先創(chuàng)建一個字符串對象“hello world”剖毯,而這個字符串實際上是放在字符串緩沖區(qū)中圾笨,然后把a指向這個對象;而對于String b = new String("hello world");則會創(chuàng)建兩個對象一個是“hello world”這個放在字符串緩沖區(qū)中的逊谋,另一個是new 方法構(gòu)造出來的對象new String() 這個對象擂达,新對象中保存的是“hello world”對象罷了,這個對象是放在堆內(nèi)存中胶滋,而b 指向這個new String ()對象板鬓,這顯然是不同的兩個對象,所以他們用 “=”比較的結(jié)果為false究恤。
如果用equals()方法比較俭令,這結(jié)果為true,因為equals()方法比較的是對象的內(nèi)容丁溅,它們的內(nèi)容都為“hello world”唤蔗。
另外值得提醒的是,字符串緩沖區(qū)中對相同的字符串只會存一次窟赏。假如我們同時寫了String a ="hello world";String b = new String("hello world");那么字符串緩沖區(qū)實際只有一個hello world 字符串箱季,在給b賦值時涯穷,會先檢查字符串緩沖區(qū)中是否有“hello world”這個字符串,如果有則不創(chuàng)建藏雏,直接new String()拷况,然后賦值作煌,因此這種情況下,表達(dá)式String b= new String ("hello world")也只創(chuàng)建了一個對象赚瘦。
總結(jié):
棧內(nèi)存:局部變量粟誓,對象的引用,基本數(shù)據(jù)類型
堆內(nèi)存:全局變量起意,包裝類鹰服,對象;
————————————————
原文鏈接:https://blog.csdn.net/qq_33371372/article/details/81383312