值类型和引用类型的区别
一、定義
引用類型表示你操作的數(shù)據(jù)是同一個(gè),也就是說(shuō)當(dāng)你傳一個(gè)參數(shù)給另一個(gè)方法時(shí),你在另一個(gè)方法中改變這個(gè)變量的值,那么調(diào)用這個(gè)方法是傳入的變量的值也將改變。
值類型表示復(fù)制一個(gè)當(dāng)前變量傳給方法,當(dāng)你在這個(gè)方法中改變這個(gè)變量的值時(shí),最初生命的變量的值不會(huì)變。
值類型
也就是基本數(shù)據(jù)類型 基本數(shù)據(jù)類型常被稱為四類八種。
四類八種:
整型(4種):byte(1 byte)、short(2 byte)、int(4 byte)、long(8 byte)
浮點(diǎn)型(2種):float(4 byte)、double(8 byte)
字符型(1種):char(2 byte)
邏輯型(1種):boolean
引用類型
除了八種基本數(shù)據(jù)類型外,其他所有的類型都稱為引用類型(數(shù)組、類、接口、字符串等)
在弄清楚值類型與引用類型之后,最后一點(diǎn)就是值傳遞與引用傳遞,這才是關(guān)鍵
值傳遞
基本數(shù)據(jù)類型賦值都屬于值傳遞,值傳遞傳遞的是實(shí)實(shí)在在的變量值,是傳遞原參數(shù)的拷貝,值傳遞后,實(shí)參傳遞給形參的值,形參發(fā)生改變而不影響實(shí)參。
引用傳遞
引用類型之間賦值屬于引用傳遞。引用傳遞傳遞的是對(duì)象的引用地址,也就是它的本身(自己最通俗的理解)。引用傳遞:傳的是地址,就是將實(shí)參的地址傳遞給形參,形參改變了,實(shí)參當(dāng)然被改變了,因?yàn)樗麄冎赶蛳嗤牡刂贰?/p>
引用和我們的指針差不多,但是它不又不需要我們?nèi)ゾ唧w的操作。
二、區(qū)別
三、內(nèi)存分配
值類型
值類型(value type)的數(shù)據(jù)存放在棧內(nèi)的一個(gè)變量中。即是在棧中分配內(nèi)存空間,直接存儲(chǔ)所包含的值,其值就代表數(shù)據(jù)本身。
但是也有特殊情況,如果某個(gè)類的實(shí)例有個(gè)值類型的字段,那么實(shí)際上該字段會(huì)和類實(shí)例保存在同一個(gè)地方,即堆中。不過(guò)引用類型的對(duì)象總是存儲(chǔ)在堆中;如果一個(gè)結(jié)構(gòu)的字段是引用類型,那么只有引用本身是和結(jié)構(gòu)實(shí)例存儲(chǔ)在一起的(在棧或堆上,視情況而定)。
值類型的數(shù)據(jù)具有較快的存取速度。
引用類型
引用類型(reference type)的數(shù)據(jù)并不駐留在棧中,而是存儲(chǔ)于堆中。即是在堆中分配內(nèi)存空間,存儲(chǔ)所包含的值,而棧中存儲(chǔ)的是指向該值的地址。當(dāng)訪問(wèn)一個(gè)具有引用類型的數(shù)據(jù)時(shí),需要到棧中檢查變量的內(nèi)容,該變量引用堆中的一個(gè)實(shí)際數(shù)據(jù)。引用類型的數(shù)據(jù)比值類型的數(shù)據(jù)具有更大的存儲(chǔ)規(guī)模和較低的訪問(wèn)速度。
注:
棧(stack)是一種后進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)。在內(nèi)存中,變量會(huì)被分配在棧上來(lái)進(jìn)行操作。堆(heap)是用于為類型實(shí)例(對(duì)象)分配空間的內(nèi)存區(qū)域,在堆上創(chuàng)建一個(gè)對(duì)象,會(huì)將對(duì)象的地址傳給棧上的變量(反過(guò)來(lái)叫變量指向此對(duì)象,或者變量引用此對(duì)象)。
值類型總是分配在它聲明的地方:作為字段時(shí),跟隨其所屬的變量(實(shí)例)存儲(chǔ);作為局部變量時(shí),存儲(chǔ)在棧上。
值類型在內(nèi)存管理方面具有更好的效率,并且不支持多態(tài),適合用做存儲(chǔ)數(shù)據(jù)的載體;
引用類型支持多態(tài),適合用于定義 應(yīng)用程序的行為。
四、回收機(jī)制
當(dāng)一個(gè)堆內(nèi)存中的對(duì)象沒(méi)有被棧內(nèi)存中表示地址的值“引用”時(shí),這個(gè)對(duì)象就被稱為垃圾對(duì)象,它無(wú)法被使用但卻占據(jù)著內(nèi)存中的區(qū)域,好比這樣:
String s = new String("person"); s = new String("man");s本來(lái)是指向堆內(nèi)存中值為person的對(duì)象的,但是s突然討厭person了,它指向了堆內(nèi)存中的man對(duì)象了,person就像一個(gè)孤兒一樣被s遺棄了,但是person比孤兒還要慘,因?yàn)闆](méi)有什么能找的到它,除了位高權(quán)重的‘垃圾回收器’,不過(guò)被當(dāng)官的找到往往沒(méi)什么好事,尤其是這個(gè)‘垃圾回收器’,它會(huì)豪不留情把‘垃圾’們清理走,并且無(wú)情的銷毀,以便釋放內(nèi)存。
Java中有垃圾回收機(jī)制,棧內(nèi)存中的變量隨著方法的結(jié)束內(nèi)存自然銷毀了,而用引用類型的時(shí)候,當(dāng)方法結(jié)束的時(shí)候,這個(gè)對(duì)象可能被另一個(gè)引用類型所應(yīng)用,不會(huì)銷毀,只有當(dāng)一個(gè)對(duì)象沒(méi)有任何引用變量引用的時(shí)候,垃圾回收機(jī)制才會(huì)回收。
五、為什么Java中數(shù)據(jù)的存放有堆和棧之分?
答:當(dāng)一個(gè)方法執(zhí)行時(shí),每個(gè)方法都會(huì)建立自己的內(nèi)存棧,在這個(gè)方法內(nèi)定義的變量將會(huì)逐個(gè)放入這塊棧內(nèi)存里,隨著方法的執(zhí)行結(jié)束,這個(gè)方法的內(nèi)存棧也將自然銷毀了。因此,所有在方法中定義的變量都是放在棧內(nèi)存中的;當(dāng)我們?cè)诔绦蛑袆?chuàng)建一個(gè)對(duì)象時(shí),這個(gè)對(duì)象將被保存到運(yùn)行時(shí)數(shù)據(jù)區(qū)中,以便反復(fù)利用(因?yàn)閷?duì)象的創(chuàng)建成功通常較大),這個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū)就是堆內(nèi)存。堆內(nèi)存中的對(duì)象不會(huì)隨方法的結(jié)束而銷毀,即使方法結(jié)束后,這個(gè)對(duì)象還可能被另一個(gè)引用變量所引用(方法的參數(shù)傳遞時(shí)很常見(jiàn)),則這個(gè)對(duì)象依然不會(huì)被銷毀。只有當(dāng)一個(gè)對(duì)象沒(méi)有任何引用變量引用它時(shí),系統(tǒng)的垃圾回收機(jī)制才會(huì)在合適的時(shí)候回收它。
六、裝箱與拆箱
裝箱:
裝箱就是值類型到引用類型的轉(zhuǎn)化過(guò)程。將一個(gè)值類型變量裝箱成一個(gè)引用類型變量,首先會(huì)在托管堆上為新的引用類型變量分配內(nèi)存空間,然后將值類型變量拷貝到托管堆上新分配的對(duì)象內(nèi)存中,最后返回新分配的對(duì)象內(nèi)存地址。
拆箱:
裝箱操作是可逆的,所以還有拆箱操作。拆箱操作獲取只想對(duì)象中包含值類型部分的指針,然后由程序員手動(dòng)將其對(duì)應(yīng)的值拷貝給值類型變量。
總結(jié)
以上是生活随笔為你收集整理的值类型和引用类型的区别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: VS引用文件出现黄色感叹号丢失文件,应该
- 下一篇: Qt Creator的安装与Qt交叉编译