日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java中的几种引用类型_Java中的几种引用类型(转载)

發(fā)布時(shí)間:2025/5/22 java 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中的几种引用类型_Java中的几种引用类型(转载) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Java中的對象引用主要有以下幾種類型:

1)強(qiáng)可及對象(strongly reachable):

可以通過強(qiáng)引用訪問的對象,一般來說,我們平時(shí)寫代碼的方式都是使用的強(qiáng)引用對象,比如下邊的代碼段:

StringBuilder builder= new StringBuilder();

上邊代碼部分引用obj這個(gè)引用將引用內(nèi)存堆中的一個(gè)對象,這種情況下,只要obj的引用存在,垃圾回收器就永遠(yuǎn)不會(huì)釋放該對象的存儲(chǔ)空間。這種對象我們又成為強(qiáng)引用(Strong references),這種強(qiáng)引用方式就是Java語言的原生的Java引用,我們幾乎每天編程的時(shí)候都用到。上邊代碼JVM存儲(chǔ)了一個(gè)StringBuilder類型的對象的強(qiáng)引用在變量builder。強(qiáng)引用和GC的交互是這樣的,如果一個(gè)對象通過強(qiáng)引用可達(dá)或者通過強(qiáng)引用鏈可達(dá)的話這種對象就成為強(qiáng)可及對象,這種情況下的對象垃圾回收器不予理睬。如果我們開發(fā)過程不需要垃圾回器回收該對象,就直接將該對象賦為強(qiáng)引用。

2)軟可及對象(softly reachable):

不通過強(qiáng)引用訪問的對象,即不是強(qiáng)可及對象,但是可以通過軟引用訪問的對象就成為軟可及對象,軟可及對象就需要使用類SoftReference(java.lang.ref.SoftReference)。此種類型的引用主要用于內(nèi)存比較敏感的高速緩存,而且此種引用還是具有較強(qiáng)的引用功能,當(dāng)內(nèi)存不夠的時(shí)候GC會(huì)回收這類內(nèi)存,因此如果內(nèi)存充足的時(shí)候,這種引用通常不會(huì)被回收的。不僅僅如此,這種引用對象在JVM里面保證在拋出OutOfMemory異常之前,設(shè)置成為null。通俗地講,這種類型的引用會(huì)在JVM內(nèi)存不足的時(shí)候全部被清除,但是有個(gè)關(guān)鍵在于:垃圾收集器在運(yùn)行時(shí)是否釋放軟可及對象是不確定的,而且使用垃圾回收算法并不能保證一次性尋找到所有的軟可及對象。當(dāng)垃圾回收器每次運(yùn)行的時(shí)候都可以隨意釋放不是強(qiáng)可及對象占用的內(nèi)存,如果垃圾回收器找到了軟可及對象過后,可能會(huì)進(jìn)行以下操作:

1. 將SoftReference對象的referent域設(shè)置成為null,從而使該對象不再引用heap對象。

2. SoftReference引用過的內(nèi)存堆上的對象一律被生命為finalizable。

3. 當(dāng)內(nèi)存堆上的對象finalize()方法被運(yùn)行而且該對象占用的內(nèi)存被釋放,SoftReference對象就會(huì)被添加到它的ReferenceQueue,前提條件是ReferenceQueue本身是存在的。

既然Java里面存在這樣的對象,那么我們在編寫代碼的時(shí)候如何創(chuàng)建這樣的對象呢?創(chuàng)建步驟如下:

先創(chuàng)建一個(gè)對象,并使用普通引用方式(強(qiáng)引用),然后再創(chuàng)建一個(gè)SoftReference來引用該對象,最后將普通引用設(shè)置為null,通過這樣的方式,這個(gè)對象就僅僅保留了一個(gè)SoftReference引用,同時(shí)這種情況我們所創(chuàng)建的對象就是SoftReference對象。一般情況下,我們可以使用該引用來完成Cache功能,就是前邊說的用于高速緩存,保證最大限度使用內(nèi)存而不會(huì)引起內(nèi)存泄漏的情況。下邊的代碼段:

public static void main(String args[])

{

//創(chuàng)建一個(gè)強(qiáng)可及對象

A a = new A();

//創(chuàng)建這個(gè)對象的軟引用SoftReference

SoftReference sr = new SoftReference(a);

//將強(qiáng)引用設(shè)置為空,以便垃圾回收器回收強(qiáng)引用

a = null;

//下次使用該對象的操作

if( sr != null ){

a = (A)sr.get();

}else{

//這種情況就是由于內(nèi)存過低,已經(jīng)將軟引用釋放了,因此需要重新裝載一次

a = new A();

sr = new SoftReference(a);

}

}

軟引用技術(shù)使得Java系統(tǒng)可以更好地管理內(nèi)存,保持系統(tǒng)穩(wěn)定,防止內(nèi)存泄漏,避免系統(tǒng)崩潰,因此在處理一些內(nèi)存占用大而且生命周期長使用不頻繁的對象可以使用該技術(shù)。

3)弱可及對象(weakly reachable):

不是強(qiáng)可及對象同樣也不是軟可及對象,僅僅通過弱引用WeakReference(java.lang.ref.WeakReference)訪問的對象,這種對象的用途在于規(guī)范化映射(canonicalized mapping),對于生存周期相對比較長而且重新創(chuàng)建的時(shí)候開銷少的對象,弱引用也比較有用,和軟引用對象不同的是,垃圾回收器如果碰到了弱可及對象,將釋放WeakReference對象的內(nèi)存,但是垃圾回收器需要運(yùn)行很多次才能夠找到弱可及對象。弱引用對象在使用的時(shí)候,可以配合ReferenceQueue類使用,如果弱引用被回收,JVM就會(huì)把這個(gè)弱引用加入到相關(guān)的引用隊(duì)列中去。最簡單的弱引用方法如以下代碼:

WeakReference weakWidget = new WeakReference(classA);

在上邊代碼里面,當(dāng)我們使用weakWidget.get()來獲取classA的時(shí)候,由于弱引用本身是無法阻止垃圾回收的,所以我們也許會(huì)拿到一個(gè)null為返回。(*:這里提供一個(gè)小技巧,如果我們希望取得某個(gè)對象的信息,但是又不影響該對象的垃圾回收過程,我們就可以使用WeakReference來記住該對象,一般我們在開發(fā)調(diào)試器和優(yōu)化器的時(shí)候使用這個(gè)是很好的一個(gè)手段。)

如果上邊的代碼部分,我們通過weakWidget.get()返回的是null就證明該對象已經(jīng)被垃圾回收器回收了,而這種情況下弱引用對象就失去了使用價(jià)值,GC就會(huì)定義為需要進(jìn)行清除工作。這種情況下弱引用無法引用任何對象,所以在JVM里面就成為了一個(gè)死引用,這就是為什么我們有時(shí)候需要通過ReferenceQueue類來配合使用的原因,使用了ReferenceQueue過后,就使得我們更加容易監(jiān)視該引用的對象,如果我們通過一ReferenceQueue類來構(gòu)造一個(gè)弱引用,當(dāng)弱引用的對象已經(jīng)被回收的時(shí)候,系統(tǒng)將自動(dòng)使用對象引用隊(duì)列來代替對象引用,而且我們可以通過ReferenceQueue類的運(yùn)行來決定是否真正要從垃圾回收器里面將該死引用(Dead Reference)清除。

弱引用代碼段:

//創(chuàng)建普通引用對象

MyObject object = new MyObject();

//創(chuàng)建一個(gè)引用隊(duì)列

ReferenceQueue rq = new ReferenceQueue();

//使用引用隊(duì)列創(chuàng)建MyObject的弱引用

WeakReference wr = new WeakReference(object,rq);

這里提供兩個(gè)實(shí)在的場景來描述弱引用的相關(guān)用法:

(1)你想給對象附加一些信息,于是你用一個(gè) Hashtable 把對象和附加信息關(guān)聯(lián)起來。你不停的把對象和附加信息放入 Hashtable 中,但是當(dāng)對象用完的時(shí)候,你不得不把對象再從 Hashtable 中移除,否則它占用的內(nèi)存變不會(huì)釋放。萬一你忘記了,那么沒有從 Hashtable 中移除的對象也可以算作是內(nèi)存泄漏。理想的狀況應(yīng)該是當(dāng)對象用完時(shí),Hashtable 中的對象會(huì)自動(dòng)被垃圾收集器回收,不然你就是在做垃圾回收的工作。

(2)你想實(shí)現(xiàn)一個(gè)圖片緩存,因?yàn)榧虞d圖片的開銷比較大。你將圖片對象的引用放入這個(gè)緩存,以便以后能夠重新使用這個(gè)對象。但是你必須決定緩存中的哪些圖片不再需要了,從而將引用從緩存中移除。不管你使用什么管理緩存的算法,你實(shí)際上都在處理垃圾收集的工作,更簡單的辦法(除非你有特殊的需求,這也應(yīng)該是最好的辦法)是讓垃圾收集器來處理,由它來決定回收哪個(gè)對象。

當(dāng)Java回收器遇到了弱引用的時(shí)候有可能會(huì)執(zhí)行以下操作:

1. 將WeakReference對象的referent域設(shè)置成為null,從而使該對象不再引用heap對象。

2. WeakReference引用過的內(nèi)存堆上的對象一律被生命為finalizable。

3. 當(dāng)內(nèi)存堆上的對象finalize()方法被運(yùn)行而且該對象占用的內(nèi)存被釋放,WeakReference對象就會(huì)被添加到它的ReferenceQueue,前提條件是ReferenceQueue本身是存在的。

4.. 清除:當(dāng)引用對象的referent域設(shè)置為null,并且引用類在內(nèi)存堆中引用的對象聲明為可結(jié)束的時(shí)候,該對象就可以清除,清除不做過多的講述

4)虛可及對象(phantomly reachable):

不是強(qiáng)可及對象,也不是軟可及對象,同樣不是弱可及對象,之所以把虛可及對象放到最后來講,主要也是因?yàn)樗奶厥庑?#xff0c;有時(shí)候我們又稱之為“幽靈對象”,已經(jīng)結(jié)束的,可以通過虛引用來訪問該對象。我們使用類PhantomReference(java.lang.ref.PhantomReference)來訪問,這個(gè)類只能用于跟蹤被引用對象進(jìn)行的收集,同樣的,可以用于執(zhí)行per-mortern清除操作。PhantomReference必須與ReferenceQueue類一起使用。需要使用ReferenceQueue是因?yàn)樗軌虺洚?dāng)通知機(jī)制,當(dāng)垃圾收集器確定了某個(gè)對象是虛可及對象的時(shí)候,PhantomReference對象就被放在了它的ReferenceQueue上,這就是一個(gè)通知,表明PhantomReference引用的對象已經(jīng)結(jié)束,可以收集了,一般情況下我們剛好在對象內(nèi)存在回收之前采取該行為。這種引用不同于弱引用和軟引用,這種方式通過get()獲取到的對象總是返回null,僅僅當(dāng)這些對象在ReferenceQueue隊(duì)列里面的時(shí)候,我們可以知道它所引用的哪些對對象是死引用(Dead Reference)。而這種引用和弱引用的區(qū)別在于:

弱引用(WeakReference)是在對象不可達(dá)的時(shí)候盡快進(jìn)入ReferenceQueue隊(duì)列的,在finalization方法執(zhí)行和垃圾回收之前是確實(shí)會(huì)發(fā)生的,理論上這類對象是不正確的對象,但是WeakReference對象可以繼續(xù)保持Dead狀態(tài),

虛引用(PhantomReference)是在對象確實(shí)已經(jīng)從物理內(nèi)存中移除過后才進(jìn)入的ReferenceQueue隊(duì)列,而且get()方法會(huì)一直返回null

當(dāng)垃圾回收器遇到了虛引用的時(shí)候?qū)⒂锌赡軋?zhí)行以下操作:

1. PhantomReference引用過的heap對象聲明為finalizable;

2. 虛引用在堆對象釋放之前就添加到了它的ReferenceQueue里面,這種情況使得我們可以在堆對象被回收之前采取操作(*:再次提醒,PhantomReference對象必須經(jīng)過關(guān)聯(lián)的ReferenceQueue來創(chuàng)建,就是說必須和ReferenceQueue類配合操作)

看似沒有用處的虛引用,有什么用途呢?

1. 首先,我們可以通過虛引用知道對象究竟什么時(shí)候真正從內(nèi)存里面移除的,而且這也是唯一的途徑。

2. 虛引用避過了finalize()方法,因?yàn)閷τ诖朔椒ǖ膱?zhí)行而言,虛引用真正引用到的對象是異常對象,若在該方法內(nèi)要使用對象只能重建。一般情況垃圾回收器會(huì)輪詢兩次,一次標(biāo)記為finalization,第二次進(jìn)行真實(shí)的回收,而往往標(biāo)記工作不能實(shí)時(shí)進(jìn)行,或者垃圾回收其會(huì)等待一個(gè)對象去標(biāo)記finalization。這種情況很有可能引起MemoryOut,而使用虛引用這種情況就會(huì)完全避免。因?yàn)樘撘迷谝脤ο蟮倪^程不會(huì)去使得這個(gè)對象由Dead復(fù)活,而且這種對象是可以在回收周期進(jìn)行回收的。

在JVM內(nèi)部,虛引用比起使用finalize()方法更加安全一點(diǎn)而且更加有效。而finaliaze()方法回收在虛擬機(jī)里面實(shí)現(xiàn)起來相對簡單,而且也可以處理大部分工作,所以我們?nèi)匀皇褂眠@種方式來進(jìn)行對象回收的掃尾操作,但是有了虛引用過后我們可以選擇是否手動(dòng)操作該對象使得程序更加高效完美。

總結(jié)

以上是生活随笔為你收集整理的Java中的几种引用类型_Java中的几种引用类型(转载)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。