Java的引用類型常用的四種方法
前言
今天看代碼看到有牽扯到弱引用的東西,就先稍微補(bǔ)一補(bǔ)Java的四種引用類型吧。Java為引用類型專門(mén)定義了一個(gè)類Reference
,它是引用對(duì)象的抽象基類。
這個(gè)類定義了所有引用對(duì)象共有的操作。 由于這個(gè)類和垃圾收集器是息息相關(guān)的,這個(gè)類不能直接子類化。
Reference有4個(gè)子類,分別為強(qiáng)引用FinalReference、軟引用SoftReference、弱引用weakReference、虛引用PhantomReference。
意思就是這四種引用是在JVM中GC用的,我們工作寫(xiě)代碼根本用不著。
強(qiáng)引用FinalReference
Object obj = new Object();
上面我們new了一個(gè)Object對(duì)象,并將其賦值給obj,這個(gè)obj就是new Object()的強(qiáng)引用。
Java中的引用默認(rèn)就是強(qiáng)引用。
強(qiáng)引用的特性是只要有強(qiáng)引用存在,被引用的對(duì)象就不會(huì)被垃圾回收。只有強(qiáng)引用不存在了,被引用的對(duì)象才會(huì)被垃圾回收。
寫(xiě)個(gè)demo吧,新建一個(gè)BeanA,重寫(xiě)finalize方法:
public class BeanA { @Override protected void finalize(){ System.out.println("將對(duì)象從內(nèi)存中清除出去"); } }
然后寫(xiě)個(gè)測(cè)試方法,將強(qiáng)引用置為空后,通知JVM垃圾回收。
public static void main(String[] args) throws IOException { BeanA a = new BeanA(); a=null; System.gc(); //防止gc線程結(jié)束后還未執(zhí)行finalize方法 System.in.read(); }
輸出結(jié)果:將對(duì)象從內(nèi)存中清除出去。
可以看到強(qiáng)引用不存在了,被引用的對(duì)象是可以被垃圾回收的。
軟引用SoftReference
軟引用是用于描述一些有用但非必需的引用。
SoftReference的實(shí)例保存一個(gè)Java對(duì)象的軟引用,該軟引用的存在不影響垃圾回收線程對(duì)該Java對(duì)象的回收。
意思就是只有在內(nèi)存不足的情況下,被引用的對(duì)象才會(huì)被回收,內(nèi)存夠用是不會(huì)被回收的。
只要垃圾回收器沒(méi)有回收它,該對(duì)象就可以被程序使用。和這個(gè)軟引用是沒(méi)有關(guān)系的(即沒(méi)有將軟引用置空),只和內(nèi)存有關(guān)。
直接看demo:
public static void main(String[] args){ SoftReference<byte[]> soft = new SoftReference<>(new byte[1024*1024*10]); System.out.println(soft.get()); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.gc(); //注釋掉下面這句兩次get()方法都能獲取到 //byte[] bytes = new byte[1024 * 1024 * 15]; System.out.println(soft.get()); }
我們創(chuàng)建了一個(gè)SoftReference對(duì)象,其變量名soft強(qiáng)引用著這個(gè)SoftReference對(duì)象,而這個(gè)SoftReference對(duì)象則保存著一個(gè)軟引用,這個(gè)軟引用引用的是一個(gè)10M的數(shù)組。
當(dāng)然這個(gè)10M數(shù)組也可以替換成自己新建的對(duì)象:
A a=new A(); SoftReference<A> soft =new SoftReference<>(a);
這樣的話SoftReference對(duì)象中保存的a就變成了軟引用,如果內(nèi)存足夠的話,將a=null,GC后使用soft.get還是可以獲取到該對(duì)象。
我們這里使用10M數(shù)組來(lái)測(cè)試,啟動(dòng)測(cè)試類設(shè)定VM內(nèi)存20M,發(fā)現(xiàn)再新建一個(gè)15M數(shù)組后會(huì)將原來(lái)的10M數(shù)組給GC掉。
輸出結(jié)果:
[B@2cfb4a64
[B@2cfb4a64[B@2cfb4a64
null
總結(jié)一句話就是:創(chuàng)建強(qiáng)引用時(shí)內(nèi)存不夠就把軟引用占的內(nèi)存給回收掉。
總結(jié)一個(gè)詞就是:欺軟怕硬。
另外軟引用非常適合緩存使用。
弱引用weakReference
弱引用和軟引用很類似,不同的是弱引用引用的對(duì)象只要垃圾回收?qǐng)?zhí)行,就會(huì)被回收,而不管是否內(nèi)存不足。
我demo沒(méi)有設(shè)定vm:Xmx=20M,通知JVM進(jìn)行垃圾回收后依然會(huì)將被引用對(duì)象回收掉。
public static void main(String[] args){ WeakReference<byte[]> soft = new WeakReference<>(new byte[1024*1024*10]); System.out.println(soft.get()); //通知JVM進(jìn)行垃圾回收 System.gc(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(soft.get()); }
輸出結(jié)果:
[B@2cfb4a64
null
虛引用PhantomReference
首先,虛引用是無(wú)法通過(guò)get方法來(lái)獲取的。一個(gè)虛引用對(duì)象被回收時(shí)會(huì)被放在一個(gè)ReferenceQueue隊(duì)列中,意思就是虛引用回收時(shí)會(huì)給出一個(gè)信號(hào)放在隊(duì)列中。
ReferenceQueue<Object> rq = new ReferenceQueue<>(); Object obj = new Object(); PhantomReference<Object> phantomReference = new PhantomReference<>(obj,rq); obj = null; System.out.println("Reference: "+phantomReference.get()); System.gc(); Reference<Object> r = (Reference<Object>)rq.poll(); System.out.println("ReferenceQueue: "+r);
輸出結(jié)果兩個(gè)null。只有VM內(nèi)存不足時(shí)才會(huì)回收這個(gè)虛引用,才會(huì)將其放在隊(duì)列中,才能通過(guò)poll()獲取到隊(duì)列中的PhantomReference對(duì)象,而這個(gè)引用對(duì)象需要程序員自己進(jìn)行特殊處理。
那問(wèn)題來(lái)了,甭管G不GC我都拿不到它,那它有啥用?
其實(shí)它一般用來(lái)管理直接內(nèi)存,我們的垃圾回收器是在JVM中管理內(nèi)存的,如果我們從網(wǎng)絡(luò)中下載一個(gè)文件保存在os的內(nèi)存中,而 新版JVM不需要copy一份到j(luò)vm內(nèi)存中,通過(guò)引用可以直接訪問(wèn)操作系統(tǒng)管理的內(nèi)存,當(dāng)我們回收這個(gè)虛引用時(shí),則會(huì)在隊(duì)列中放入這個(gè)引入對(duì)象,方便用來(lái)特殊處理。
到此這篇關(guān)于Java的引用類型常用的四種方法的文章就介紹到這了,更多相關(guān)Java引用類型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis Trim標(biāo)簽用法簡(jiǎn)單介紹
這篇文章主要介紹了Mybatis Trim標(biāo)簽用法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-05-05java開(kāi)發(fā)SSM框架具有rest風(fēng)格的SpringMVC
這篇文章主要介紹了java開(kāi)發(fā)中如何使SSM框架具有rest風(fēng)格的SpringMVC實(shí)現(xiàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10WebsocketClient斷線的一些常見(jiàn)原因及解決辦法
這篇文章主要給大家介紹了關(guān)于WebsocketClient斷線的一些常見(jiàn)原因及解決辦法,文中通過(guò)代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用WebsocketClient斷線具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-12-12Java?PTA?計(jì)算3到7位?水仙花數(shù)實(shí)例
這篇文章主要介紹了Java?PTA?計(jì)算3到7位?水仙花數(shù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03C# 中Excel導(dǎo)入時(shí)判斷是否被占用三種方法
這篇文章主要介紹了C# 中Excel導(dǎo)入時(shí) 判斷是否被占用三種方法的相關(guān)資料,需要的朋友可以參考下2017-04-04Java如何實(shí)現(xiàn)多個(gè)線程之間共享數(shù)據(jù)
這篇文章主要介紹了Java如何實(shí)現(xiàn)多個(gè)線程之間共享數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11詳解springboot集成websocket的兩種實(shí)現(xiàn)方式
這篇文章主要介紹了springboot集成websocket的兩種實(shí)現(xiàn)方式,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01SpringBoot2 整合FreeMarker實(shí)現(xiàn)頁(yè)面靜態(tài)化示例詳解
這篇文章主要介紹了SpringBoot2 整合FreeMarker實(shí)現(xiàn)頁(yè)面靜態(tài)化示例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07