Android中深入學(xué)習(xí)對(duì)象的四種引用類型
前言:
Java中,一切被視為對(duì)象,引用則是用來(lái)操縱對(duì)象的;在JDK1.2就把對(duì)象引用分為四種級(jí)別,從而使程序能更靈活控制它的生命周期,級(jí)別由高到底依次為:強(qiáng) > 軟 > 弱 > 虛引用;而GC
垃圾回收器(Garbage Collection
)對(duì)不同的類型有著不同的處理方法,了解這些處理方式有助于我們寫出更高質(zhì)量的代碼。今天我們就來(lái)學(xué)習(xí)下
一、引用詳解
1、強(qiáng)引用 StrongReference
強(qiáng)引用是使用最普遍的引用。如果一個(gè)對(duì)象具有強(qiáng)引用,那垃圾回收器絕不會(huì)回收它。當(dāng)內(nèi)存空間不足,Java
虛擬機(jī)寧愿拋出 OutOfMemoryError
錯(cuò)誤,使程序異常終止,也不會(huì)靠隨意回收具有強(qiáng)引用的對(duì)象來(lái)解決內(nèi)存不足的問題。如代碼 String s=”abc”
中變量 s 就是字符串對(duì)象”abc
” 的一個(gè)強(qiáng)引用。只要你給強(qiáng)引用對(duì)象 s
賦空值 null
, 該對(duì)象就可以被垃圾回收器回收;因?yàn)樵搶?duì)象此時(shí)不再含有其他強(qiáng)引用;
//str表示強(qiáng)引用,指向new String()這個(gè)對(duì)象 String str = new String();
2、弱引用
弱引用(WeakReference
)是弱于軟引用的引用類型,與軟引用類似,不同的是弱引用不能阻止垃圾回收,在垃圾回收機(jī)制運(yùn)行時(shí),如果一個(gè)對(duì)象的引用是弱引用的話,不管內(nèi)存空間是否足夠,對(duì)象都會(huì)被回收。弱引用常常被用于防止內(nèi)存泄漏,最常見的是單例和Handler
造成的內(nèi)存泄漏;
//弱引用實(shí)例 WeakReference weakReference = new WeakReference<>(context); //獲取弱引用保存的引用 Context ctx = weakReference.get();
3、軟引用
SoftReference:
軟引用–>當(dāng)虛擬機(jī)內(nèi)存不足時(shí),將會(huì)回收它指向的對(duì)象;需要獲取對(duì)象時(shí),可以調(diào)用get
方法;
軟引用對(duì)象不會(huì)很快被jvm
回收,jvm
會(huì)根據(jù)當(dāng)前堆的使用情況來(lái)判斷何時(shí)回收,當(dāng)堆的使用頻率接近閥值時(shí)才會(huì)被回收;
基本用法:
MySoftReference msf = new MySoftReference(); SoftReference sf = new SoftReference(msf); MySoftReference mySoftReference =(MySoftReference) sf.get();
基本特點(diǎn):
- 如果內(nèi)存足夠,軟引用是不會(huì)被jvm回收的;
- 如果內(nèi)存不夠,會(huì)根據(jù)堆棧的使用情況來(lái)回收引用;
- 未被回收的軟引用是一直可被程序占有的;
- 軟引用可以和引用隊(duì)列(ReferenceQueue)聯(lián)合使用來(lái)實(shí)現(xiàn)內(nèi)存緊張的高速緩存;
- 如果軟引用引用的對(duì)象被回收,Java虛擬機(jī)會(huì)把改軟引用對(duì)象加到與之關(guān)聯(lián)的引用隊(duì)列中;
ReferenceQueue rq = new ReferenceQueue(); SoftReference sf = new SoftReference(msf,rf);
當(dāng)軟引用對(duì)象被回收后,ReferenceQueue
隊(duì)列中存儲(chǔ)著強(qiáng)引用的Reference
,然后可通過poll()
來(lái)判斷當(dāng)前引用隊(duì)列是否有失去軟引用的對(duì)象,如果隊(duì)列為空,將返回一個(gè)null
,否則該方法返回隊(duì)列中前面的一個(gè)Reference
對(duì)象??梢詸z測(cè)出哪個(gè)軟引用對(duì)象被回收,然后將其清除;
Reference reference =null; while((reference==(EmployeeRef)rq.poll())){ //清除操作 reference =null; System.gc(); }
4、虛引用
虛引用(PhantomReference
)是最弱的引用,一個(gè)持有虛引用的對(duì)象和沒有引用幾乎是一樣的,隨時(shí)都可能被垃圾回收器回收。通過虛引用的get()方法獲取到的引用都會(huì)失敗(為null
),虛引用必須和引用隊(duì)列ReferenceQueue
一起使用;
ReferenceQueue
引用隊(duì)列作用在于跟蹤垃圾回收過程。當(dāng)垃圾回收器回收對(duì)象時(shí),如果發(fā)現(xiàn)它還有虛引用,就會(huì)在回收后銷毀這個(gè)對(duì)象,并且將虛引用指向的對(duì)象加入到引用隊(duì)列。只能通過虛引用是否被加入到ReferenceQueue
來(lái)判斷虛引用是否為GC回收,這也是判斷對(duì)象是否為回收的唯一途徑;
Java的Object類中有finalize()方法,原理:一旦垃圾回收器準(zhǔn)備釋放對(duì)象占用的內(nèi)存空間,將首先調(diào)用finalize()
方法,并且在下一次垃圾回收動(dòng)作發(fā)生時(shí),才會(huì)真正回收對(duì)象占用的內(nèi)存,但是問題在于,虛擬機(jī)不能保證finalize()
何時(shí)被調(diào)用,因?yàn)?code>GC運(yùn)行時(shí)間不是固定的;
使用虛引用就能解決這個(gè)問題,虛引用主要用于跟蹤垃圾被回收的活動(dòng),主要用來(lái)實(shí)現(xiàn)比較精細(xì)的內(nèi)存使用控制,這對(duì)Android
來(lái)說(shuō)很有意義;
//引用隊(duì)列 ReferenceQueue queue = new ReferenceQueue<>(); //虛引用 PhantomReference phantomReference = new PhantomReference(new Object(), queue); Log.e(TAG, "虛引用:PhantomReference == " + phantomReference.get()); //系統(tǒng)垃圾回收 System.gc(); System.runFinalization();
phantomReference.get()
獲取的引用一直為null,調(diào)用系統(tǒng)回收垃圾,queue.poll()
獲取保存的引用對(duì)象,并且把它在這個(gè)隊(duì)列中移除;
虛引用無(wú)法通過get()方
法獲取目標(biāo)的引用,一直都是返回null
,源碼:
public T get() { return null; }
總結(jié):
- 強(qiáng)引用(
StrongReference
):不會(huì)自動(dòng)回收,最難被GC
回收的,寧可拋出異常也不回收強(qiáng)引用指向的對(duì)象;任何場(chǎng)景; - 軟引用(
SoftReference
):內(nèi)存不足時(shí),GC
會(huì)回收軟引用指向的對(duì)象比較少使用,已被LruCache
替代; - 弱引用(
WeakReference
):不管內(nèi)存足不足,只要GC了都能回收弱引用指向的對(duì)象;常用于避免內(nèi)存泄漏; - 虛引用(
PhantomReference
):隨時(shí)都能回收,也稱幽靈引用,相當(dāng)于沒有指向任何實(shí)例引用;跟蹤對(duì)象是否被回收,很少使用;
到此這篇關(guān)于Android
中深入學(xué)習(xí)對(duì)象的四種引用類型的文章就介紹到這了,更多相關(guān)Android
中深入學(xué)習(xí)對(duì)象引用類型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android自定義View播放Gif動(dòng)畫的示例
本篇文章主要介紹了Android自定義View播放Gif動(dòng)畫的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2017-10-10Android開發(fā)使用Activity嵌套多個(gè)Fragment實(shí)現(xiàn)橫豎屏切換功能的方法
這篇文章主要介紹了Android開發(fā)使用Activity嵌套多個(gè)Fragment實(shí)現(xiàn)橫豎屏切換功能的方法,結(jié)合實(shí)例形式分析了Android使用Activity嵌套多個(gè)Fragment進(jìn)行橫豎屏切換的原理與具體操作技巧,需要的朋友可以參考下2017-11-11Android端實(shí)現(xiàn)單點(diǎn)登錄的方法詳解
所謂單點(diǎn)登錄就是指的同一個(gè)賬戶(id)不能在一個(gè)以上的設(shè)備上登錄對(duì)應(yīng)的用戶系統(tǒng)(排除web端和移動(dòng)端可以同時(shí)登錄的情況),例如:用戶m在A設(shè)備登錄并保持登錄狀態(tài),然后又在B設(shè)備登錄,此時(shí)A應(yīng)該要強(qiáng)制下線,m無(wú)法在A設(shè)備上繼續(xù)執(zhí)行用戶相關(guān)的操作,下面來(lái)一起看看吧。2016-11-11Android栗子の圖片驗(yàn)證碼生成實(shí)例代碼
這篇文章主要介紹了Android栗子の圖片驗(yàn)證碼生成實(shí)例代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-12-12關(guān)于Android HTML5 audio autoplay無(wú)效問題的解決方案
這篇文章主要介紹了關(guān)于Android HTML5 audio autoplay無(wú)效問題的解決方案,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09Android學(xué)習(xí)教程之圓形Menu菜單制作方法(1)
這篇文章主要為大家詳細(xì)介紹了Android學(xué)習(xí)教程之圓形Menu菜單操作代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Android項(xiàng)目中引入aar包的正確方法介紹
生成aar之后下一步就是如何引用本地的aar文件,下面這篇文章主要給大家介紹了關(guān)于Android項(xiàng)目中引入aar包的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08