引語:
我們知道java相比C,C++中沒有令人頭痛的指針,但是卻有和指針作用相似的引用對(duì)象(Reference),就是常說的引用寇损,比如,Object obj = new Object()裳食;這個(gè)obj就是引用矛市,它指向的是真正的對(duì)象Object的地址,不過今天要說的是java中的四種引用诲祸。有人可能比較懵逼浊吏,四種引用?是的救氯,從JDK1.2之后找田,java對(duì)引用這塊的概念進(jìn)行了擴(kuò)充,按照引用的強(qiáng)度分為了四種引用:強(qiáng)引用着憨,軟引用墩衙,弱引用,虛引用甲抖。下面就讓我們來看看這四種引用都具體的情況吧漆改。
1.強(qiáng)引用
1.1介紹:
我們平時(shí)代碼中使用得最多的引用,對(duì)象的類是:StrongReference准谚。就比如上面說的Object obj = new Object()挫剑;我們?cè)偈煜げ贿^了,作為最強(qiáng)的引用氛魁,只要引用還存在著暮顺,垃圾收集器就不會(huì)將該引用給回收,即使會(huì)出現(xiàn)OOM(內(nèi)存溢出)秀存。就是說這種引用只要引用還一直指向的對(duì)象捶码,垃圾收集器是不會(huì)去管它的,所以它被稱為強(qiáng)引用或链。不過如果
Objectobj =newObject();obj =null;
obj被賦值為了null惫恼,該引用就斷了,垃圾收集器會(huì)在合適的時(shí)候回收改引用的內(nèi)存澳盐。
還有一種情況就是obj是成員變量祈纯,方法執(zhí)行完了,obj隨著被棧幀被回收了叼耙,obj引用也是一起被回收了腕窥。強(qiáng)引用的使用就不介紹了,地球人都知道筛婉。
2.軟引用
2.1介紹:
軟引用是用來描述一些有用但是非必須的對(duì)象簇爆。對(duì)應(yīng)的類是SoftReference,它被回收的時(shí)機(jī)是系統(tǒng)內(nèi)存不足的時(shí)候爽撒,如果內(nèi)存足夠入蛆,它不會(huì)被回收,內(nèi)存不足了硕勿,可能會(huì)發(fā)生OOM了哨毁,軟引用的對(duì)象就會(huì)被回收。這樣的特性是不是就像緩存源武?是的扼褪,軟引用可以用來存放緩存的數(shù)據(jù),內(nèi)存足夠的時(shí)候一直可以訪問粱栖,內(nèi)存不足的時(shí)候迎捺,需要重新創(chuàng)建或者訪問原對(duì)象。
2.2使用:
其實(shí)不管是軟引用查排,弱引用凳枝,還是虛引用,代碼中使用方式都是像下面這樣跋核,使用對(duì)應(yīng)的Reference將對(duì)象放入到構(gòu)造函數(shù)當(dāng)中岖瑰,然后使用的地方reference.get()來調(diào)用具體對(duì)象。
Objectobj =newObject();SoftReference softReference =newSoftReference<>(obj);softReference.get();
同時(shí)可以使用ReferenceQueue來把引用和引用隊(duì)列給關(guān)聯(lián)起來:
Objectobj =newObject();ReferenceQueue refQueue =newReferenceQueue<>();SoftReference softReference =newSoftReference<>(obj, refQueue);
__所謂關(guān)聯(lián)起來砂代,其實(shí)就是當(dāng)引用被回收的時(shí)候蹋订,會(huì)被添加到ReferenceQueue中,使用ReferenceQueue.poll()方法可以返回當(dāng)前可用的引用刻伊,并從隊(duì)列沖刪除__露戒。簡(jiǎn)單來說就是引用和引用隊(duì)列關(guān)聯(lián)起來(引用的構(gòu)造函數(shù)傳入隊(duì)列)椒功,然后引用被回收的時(shí)候會(huì)被添加到隊(duì)列中,然后使用poll()方法可以返回引用智什。
3.弱引用
3.1介紹:
虛引用比上面兩個(gè)引用就更菜了动漾,只要垃圾收集器掃描到了它,被弱引用關(guān)聯(lián)的對(duì)象就會(huì)被回收荠锭。被弱引用關(guān)聯(lián)對(duì)象的生命周期其實(shí)就是從對(duì)象創(chuàng)建到下一次垃圾回收旱眯。對(duì)應(yīng)的類是WeakReference。
3.2使用:
publicstaticvoidmain(String[] args) throws InterruptedException{? ? ? Object obj =newObject();? ? ? ReferenceQueue refQueue =newReferenceQueue<>();? ? ? WeakReference weakRef =newWeakReference<>(obj, refQueue);? ? ? System.out.println("引用:"+ weakRef.get());? ? ? System.out.println("隊(duì)列中的東西:"+ refQueue.poll());// 清除強(qiáng)引用, 觸發(fā)GCobj =null;? ? ? System.gc();? ? ? Thread.sleep(200);? ? ? System.out.println("引用:"+ weakRef.get());? ? ? System.out.println("引用加入隊(duì)列了嗎证九? "+ weakRef.isEnqueued());? ? ? System.out.println("隊(duì)列中的東西:"+ refQueue.poll());/**
? ? ? * 輸出結(jié)果
? ? ? * 引用:java.lang.Object@7bb11784
? ? ? * 隊(duì)列中的東西:null
? ? ? * 引用:null
? ? ? * 引用加入隊(duì)列了嗎删豺? true
? ? ? * 隊(duì)列中的東西:java.lang.ref.WeakReference@33a10788
? ? ? */}
可以看到當(dāng)強(qiáng)引用被清除,手動(dòng)觸發(fā)GC后愧怜,弱引用回收呀页,被加入到隊(duì)列中了。
3.3擴(kuò)展:
WeakHashMap跟hashMap很像拥坛,差別就在于赔桌,當(dāng)WeakHashMap的key(弱引用),指向的對(duì)象被回收了渴逻,weakhashMap中的對(duì)象也就消失了疾党。不會(huì)和HashMap一樣一直持有該對(duì)象,導(dǎo)致無法回收惨奕。
不贅述了雪位,有興趣的可以了解一下,?WeakHashMap?梨撞。
4.虛引用
4.1介紹:
虛引用是最弱的一種引用雹洗,它不會(huì)影響對(duì)象的生命周期,對(duì)象被回收跟它沒啥關(guān)系卧波。它引用的對(duì)象可以在任何時(shí)候被回收时肿,而且也無法根據(jù)虛引用來取得一個(gè)對(duì)象的實(shí)例。僅僅當(dāng)它指向的對(duì)象被回收的時(shí)候港粱,它會(huì)受到一個(gè)通知螃成。對(duì)應(yīng)的類是PhantomReference。
4.2使用:
有人就要問既然對(duì)對(duì)象回收沒影響查坪,那它有啥用(其實(shí)用處很少)寸宏,我查閱網(wǎng)上的資料說是,可以用來監(jiān)控對(duì)象的回收偿曙,和記錄日志氮凝。簡(jiǎn)單點(diǎn)說就是對(duì)象被回收的時(shí)候,和虛引用相關(guān)的隊(duì)列知道了實(shí)例對(duì)象被回收了望忆。這個(gè)時(shí)候我們可以記錄下來罩阵,知道對(duì)象是什么時(shí)候被回收的竿秆。
從而起到監(jiān)控的作用。
publicstaticvoidmain(String[] args) throws Exception {Objectabc =newObject();? ? ? ReferenceQueue refQueue =newReferenceQueue();? ? ? PhantomReference abcRef =newPhantomReference(abc, refQueue);? ? ? System.out.println("隊(duì)列中的東西:"+ refQueue.poll());? ? ? abc =null;? ? ? System.gc();? ? ? Thread.sleep(1000);? ? ? System.out.println("引用加入隊(duì)列了嗎稿壁? "+ abcRef.isEnqueued());? ? ? System.out.println("隊(duì)列中的東西:"+ refQueue.poll());/**
? ? ? ? * 輸出:
? ? ? ? * 隊(duì)列中的東西:null
? ? ? ? * 引用加入隊(duì)列了嗎幽钢? true
? ? ? ? * 隊(duì)列中的東西:java.lang.ref.PhantomReference@7bb11784
? ? ? ? */}
發(fā)現(xiàn)隊(duì)列中有引用了,就可以添加日志記錄了常摧。
5.總結(jié):
將人比作垃圾收集器,引用比作食物威创,我們來總結(jié)下四種引用:
強(qiáng)引用是毒藥落午,即使你很餓了你也不會(huì)去吃它;
軟引用是零食肚豺,不餓的時(shí)候不吃溃斋,餓了饑不擇食,零食也能填飽肚子吸申;
弱引用是飯菜梗劫,到了吃飯時(shí)間(垃圾回收),就吃飯菜截碴;
虛引用是剩菜梳侨,當(dāng)你吃完東西(回收完對(duì)象),就回剩下剩菜日丹,別人就知道你吃過飯了走哺。
我自己是一個(gè)從事了6年的Java全棧工程師,最近整理了一套適合2019年學(xué)習(xí)的Java\大數(shù)據(jù)資料哲虾,從基礎(chǔ)的Java丙躏、大數(shù)據(jù)面向?qū)ο蟮竭M(jìn)階的框架知識(shí)都有整理哦,可以來我的主頁免費(fèi)領(lǐng)取哦束凑。