Java引用類型

歡迎訪問我的博客:http://wangnan.tech

參考:

在JDK 1.2以前的版本中耙替,若一個(gè)對(duì)象不被任何變量引用菇绵,那么程序就無法再使用這個(gè)對(duì)象舌剂。也就是說砚嘴,只有對(duì)象處于可觸及(reachable)狀態(tài)魄梯,程序才能使用它。從JDK 1.2版本開始奶赠,把對(duì)象的引用分為4種級(jí)別雳殊,從而使程序能更加靈活地控制對(duì)象的生命周期。這4種級(jí)別由高到低依次為:強(qiáng)引用臀晃、軟引用觉渴、弱引用和虛引用

強(qiáng)引用(StrongReference)

強(qiáng)引用是使用最普遍的引用积仗。如果一個(gè)對(duì)象具有強(qiáng)引用疆拘,那垃圾回收器絕不會(huì)回收它。當(dāng)內(nèi)存空間不足寂曹,Java虛擬機(jī)寧愿拋出OutOfMemoryError錯(cuò)誤哎迄,使程序異常終止,也不會(huì)靠隨意回收具有強(qiáng)引用的對(duì)象來解決內(nèi)存不足的問題 ps:強(qiáng)引用其實(shí)也就是我們平時(shí)A a = new A()這個(gè)意思隆圆。

代碼

@Test  
public void strongReference() {  
    Object referent = new Object();  
      
    /** 
     * 通過賦值創(chuàng)建 StrongReference  
     */  
    Object strongReference = referent;  
      
    assertSame(referent, strongReference);  
      
    referent = null;  
    System.gc();  
      
    /** 
     * StrongReference 在 GC 后不會(huì)被回收 
     */  
    assertNotNull(strongReference);  
}  

軟引用(SoftReference)

如果一個(gè)對(duì)象只具有軟引用漱挚,則內(nèi)存空間足夠,垃圾回收器就不會(huì)回收它渺氧;如果內(nèi)存空間不足了旨涝,就會(huì)回收這些對(duì)象的內(nèi)存。只要垃圾回收器沒有回收它侣背,該對(duì)象就可以被程序使用白华。軟引用可用來實(shí)現(xiàn)內(nèi)存敏感的高速緩存(下文給出示例)慨默。
軟引用可以和一個(gè)引用隊(duì)列(ReferenceQueue)聯(lián)合使用,如果軟引用所引用的對(duì)象被垃圾回收器回收弧腥,Java虛擬機(jī)就會(huì)把這個(gè)軟引用加入到與之關(guān)聯(lián)的引用隊(duì)列中厦取。

為什么需要使用軟引用

我們知道,訪問磁盤文件管搪、訪問網(wǎng)絡(luò)資源虾攻、查詢數(shù)據(jù)庫等操作都是影響應(yīng)用程序執(zhí)行性能的重要因素,如果能重新獲取那些尚未被回收的Java對(duì)象的引用更鲁,必將減少不必要的訪問霎箍,大大提高程序的運(yùn)行速度。

代碼

@Test  
public void softReference() {  
    Object referent = new Object();  
    SoftReference<Object> softRerference = new SoftReference<Object>(referent);  
  
    assertNotNull(softRerference.get());  
      
    referent = null;  
    System.gc();  
      
    /** 
     *  soft references 只有在 jvm OutOfMemory 之前才會(huì)被回收, 所以它非常適合緩存應(yīng)用 
     */  
    assertNotNull(softRerference.get());  
}  

以下程序創(chuàng)建了一個(gè)String對(duì)象澡为、ReferenceQueue對(duì)象和WeakReference對(duì)象:

//創(chuàng)建一個(gè)強(qiáng)引用
String str = new String("hello");
//創(chuàng)建引用隊(duì)列, <String>為范型標(biāo)記漂坏,表明隊(duì)列中存放String對(duì)象的引用
ReferenceQueue<String> rq = new ReferenceQueue<String>();
//創(chuàng)建一個(gè)弱引用,它引用"hello"對(duì)象缀壤,并且與rq引用隊(duì)列關(guān)聯(lián)
//<String>為范型標(biāo)記樊拓,表明WeakReference會(huì)弱引用String對(duì)象
WeakReference<String> wf = new WeakReference<String>(str, rq);

以上程序代碼執(zhí)行完畢纠亚,內(nèi)存中引用與對(duì)象的關(guān)系如圖所示塘慕,"hello"對(duì)象同時(shí)具有強(qiáng)引用和弱引用:`

01.png

帶實(shí)線的箭頭表示強(qiáng)引用,帶虛線的箭頭表示弱引用蒂胞。從圖中可以看出图呢,此時(shí)"hello"對(duì)象被str強(qiáng)引用,并且被一個(gè)WeakReference對(duì)象弱引用骗随,因此"hello"對(duì)象不會(huì)被垃圾回收蛤织。

在以下程序代碼中,把引用"hello"對(duì)象的str變量置為null鸿染,然后再通過WeakReference弱引用的get()方法獲得"hello"對(duì)象的引用:

String str = new String("hello"); //① 
ReferenceQueue<String> rq = new ReferenceQueue<String>(); //② 
WeakReference<String> wf = new WeakReference<String>(str, rq); //③
str=null; //④取消"hello"對(duì)象的強(qiáng)引用
String str1=wf.get(); //⑤假如"hello"對(duì)象沒有被回收指蚜,str1引用"hello"對(duì)象
//假如"hello"對(duì)象沒有被回收,rq.poll()返回null
Reference<? extends String> ref=rq.poll(); //⑥

執(zhí)行完以上第④行后涨椒,內(nèi)存中引用與對(duì)象的關(guān)系下圖所示

02.png

此時(shí)"hello"對(duì)象僅僅具有弱引用摊鸡,因此它有可能被垃圾回收。假如它還沒有被垃圾回收蚕冬,那么接下來在第⑤行執(zhí)行wf.get()方法會(huì)返回 "hello"對(duì)象的引用免猾,并且使得這個(gè)對(duì)象被str1強(qiáng)引用。再接下來在第⑥行執(zhí)行rq.poll()方法會(huì)返回null囤热,因?yàn)榇藭r(shí)引用隊(duì)列中沒有任何 引用猎提。ReferenceQueue的poll()方法用于返回隊(duì)列中的引用,如果沒有則返回null旁蔼。

锨苏,在以下程序代碼中疙教,執(zhí)行完第④行后,"hello"對(duì)象僅僅具有弱引用伞租。接下來兩次調(diào)用System.gc()方法松逊,催促垃圾回收器工作,從而提高 "hello"對(duì)象被回收的可能性肯夏。假如"hello"對(duì)象被回收经宏,那么WeakReference對(duì)象的引用被加入到ReferenceQueue中, 接下來wf.get()方法返回null驯击,并且rq.poll()方法返回WeakReference對(duì)象的引用烁兰。

String str = new String("hello"); //①
ReferenceQueue<String> rq = new ReferenceQueue<String>(); //② 
WeakReference<String> wf = new WeakReference<String>(str, rq); //③
str=null; //④
//兩次催促垃圾回收器工作,提高"hello"對(duì)象被回收的可能性
System.gc(); //⑤
System.gc(); //⑥
String str1=wf.get(); //⑦ 假如"hello"對(duì)象被回收徊都,str1為null
Reference<? extends String> ref=rq.poll(); //⑧

弱引用(WeakReference)

弱引用與軟引用的區(qū)別在于:只具有弱引用的對(duì)象擁有更短暫的生命周期沪斟。在垃圾回收器線程掃描它所管轄的內(nèi)存區(qū)域的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對(duì)象暇矫,不管當(dāng)前內(nèi)存空間足夠與否主之,都會(huì)回收它的內(nèi)存。不過李根,由于垃圾回收器是一個(gè)優(yōu)先級(jí)很低的線程槽奕,因此不一定會(huì)很快發(fā)現(xiàn)那些只具有弱引用的對(duì)象。
弱引用可以和一個(gè)引用隊(duì)列(ReferenceQueue)聯(lián)合使用房轿,如果弱引用所引用的對(duì)象被垃圾回收粤攒,Java虛擬機(jī)就會(huì)把這個(gè)弱引用加入到與之關(guān)聯(lián)的引用隊(duì)列中。

代碼

@Test  
public void weakReference() {  
    Object referent = new Object();  
    WeakReference<Object> weakRerference = new WeakReference<Object>(referent);  
  
    assertSame(referent, weakRerference.get());  
      
    referent = null;  
    System.gc();  
      
    /** 
     * 一旦沒有指向 referent 的強(qiáng)引用, weak reference 在 GC 后會(huì)被自動(dòng)回收 
     */  
    assertNull(weakRerference.get());  
}  

虛引用(PhantomReference)

“虛引用”顧名思義囱持,就是形同虛設(shè)夯接,與其他幾種引用都不同,虛引用并不會(huì)決定對(duì)象的生命周期纷妆。如果一個(gè)對(duì)象僅持有虛引用盔几,那么它就和沒有任何引用一樣,在任何時(shí)候都可能被垃圾回收器回收
虛引用主要用來跟蹤對(duì)象被垃圾回收器回收的活動(dòng)掩幢。虛引用與軟引用和弱引用的一個(gè)區(qū)別在于:虛引用必須和引用隊(duì)列 (ReferenceQueue)聯(lián)合使用逊拍。當(dāng)垃圾回收器準(zhǔn)備回收一個(gè)對(duì)象時(shí),如果發(fā)現(xiàn)它還有虛引用粒蜈,就會(huì)在回收對(duì)象的內(nèi)存之前顺献,把這個(gè)虛引用加入到與之 關(guān)聯(lián)的引用隊(duì)列中。
ReferenceQueue queue = new ReferenceQueue ();
PhantomReference pr = new PhantomReference (object, queue);
程序可以通過判斷引用隊(duì)列中是否已經(jīng)加入了虛引用枯怖,來了解被引用的對(duì)象是否將要被垃圾回收注整。如果程序發(fā)現(xiàn)某個(gè)虛引用已經(jīng)被加入到引用隊(duì)列,那么就可以在所引用的對(duì)象的內(nèi)存被回收之前采取必要的行動(dòng)。

代碼

@Test  
public void phantomReferenceAlwaysNull() {  
    Object referent = new Object();  
    PhantomReference<Object> phantomReference = new PhantomReference<Object>(referent, new ReferenceQueue<Object>());  
      
    /** 
     * phantom reference 的 get 方法永遠(yuǎn)返回 null  
     */  
    assertNull(phantomReference.get());  
}  
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肿轨,一起剝皮案震驚了整個(gè)濱河市寿冕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌椒袍,老刑警劉巖驼唱,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異驹暑,居然都是意外死亡玫恳,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門优俘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來京办,“玉大人,你說我怎么就攤上這事帆焕〔研觯” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵叶雹,是天一觀的道長(zhǎng)财饥。 經(jīng)常有香客問我,道長(zhǎng)折晦,這世上最難降的妖魔是什么钥星? 我笑而不...
    開封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮筋遭,結(jié)果婚禮上打颤,老公的妹妹穿的比我還像新娘。我一直安慰自己漓滔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開白布乖篷。 她就那樣靜靜地躺著响驴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撕蔼。 梳的紋絲不亂的頭發(fā)上豁鲤,一...
    開封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音鲸沮,去河邊找鬼琳骡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛讼溺,可吹牛的內(nèi)容都是我干的楣号。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼炫狱!你這毒婦竟也來了藻懒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤视译,失蹤者是張志新(化名)和其女友劉穎嬉荆,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酷含,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鄙早,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了椅亚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝶锋。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖什往,靈堂內(nèi)的尸體忽然破棺而出扳缕,到底是詐尸還是另有隱情,我是刑警寧澤别威,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布躯舔,位于F島的核電站,受9級(jí)特大地震影響省古,放射性物質(zhì)發(fā)生泄漏粥庄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一豺妓、第九天 我趴在偏房一處隱蔽的房頂上張望惜互。 院中可真熱鬧,春花似錦琳拭、人聲如沸训堆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坑鱼。三九已至,卻和暖如春絮缅,著一層夾襖步出監(jiān)牢的瞬間鲁沥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來泰國打工耕魄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留画恰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓吸奴,卻偏偏與公主長(zhǎng)得像允扇,于是被迫代替她去往敵國和親缠局。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 強(qiáng)引用 ( Strong Reference ) 強(qiáng)引用是使用最普遍的引用蔼两。如果一個(gè)對(duì)象具有強(qiáng)引用甩鳄,那垃圾回收器絕...
    tomas家的小撥浪鼓閱讀 2,830評(píng)論 1 4
  • 概述 java.lang.ref 類庫包含一組類,為垃圾回收提供了更大的靈活性额划。 java.lang.ref 有三...
    bing__chen閱讀 416評(píng)論 0 2
  • 來源:朱小廝 鏈接:http://blog.csdn.net/u013256816/article/details...
    會(huì)點(diǎn)代碼的大叔閱讀 354評(píng)論 0 1
  • Java有四種引用類型妙啃,strongreference,softreference俊戳,weakreference揖赴,p...
    alexpdh閱讀 296評(píng)論 0 0
  • 1.強(qiáng)引用:強(qiáng)引用是使用最普遍的引用。如果一個(gè)對(duì)象具有強(qiáng)引用抑胎,那垃圾回收器絕不會(huì)回收它燥滑。當(dāng)內(nèi)存空間不足,Java虛...
    shannonxizhang閱讀 175評(píng)論 0 0