Java引用類型

Java有四種引用類型,strongreference,softreference,weakreference,phantomreference。這四種引用的強度按照上面的順序依次減弱,下面通過幾個例子簡單了解一下這四種引用類型。

StrongReference

這個不用多講了,這是java默認的引用類型,如果不特意使用java.lang.ref下的類,那么程序中的所有引用都是強引用。有強引用存在的對象永遠都不會被gc收集,所以在內存不夠用時,JVM寧愿拋出OutOfMemoryError這樣的錯誤,也不愿意將強引用對象進行回收。

SoftReference

軟引用不會保證對象一定不會被回收,只能最大可能保證。如果內存有剩余,那么軟引用對象不會被回收,如果內存不足,那么gc會回收軟引用對象。所以這種特性可以用來實現緩存技術。軟引用要用java.lang.ref.SoftReference來實現。

Java代碼

publicclassSoftTest{

publicstaticvoidmain(String[]?args)?{

Object?ref?=newObject();//ref是Object對象的強引用

//將一個軟引用指向對象,此時Object對象有兩個引用

SoftReference?sf?=newSoftReference(ref);

ref?=null;//去除對象的強引用

System.gc();//gc只有在內存不足是才會回收軟引用對象

}

}

WeakReference

除了通過java.lang.ref.WeakReference來使用弱引用,WeakHashMap同樣也利用了弱引用。

和軟引用不同的是,弱引用一定會被gc回收,不管內存是否不足。

Java代碼

publicclassWeakTest{

publicstaticvoidmain(String[]?args)?{

Object?ref?=newObject();//ref是Object對象的強引用

//將一個弱引用指向對象,此時Object對象有兩個引用

WeakReference?wf?=newWeakReference(ref);

ref?=null;//去除對象的強引用

System.gc();//gc對弱引用對象進行回收

}

}

PhantomReference

幽靈引用,也叫虛引用。java.lang.ref.PhantomReference類中只有一個方法get(),而且幾乎沒有實現,只是返回null。而且這個類只有一個構造器(軟引用和弱引用均有兩個構造器):

Java代碼

publicPhantomReference(T?referent,?ReferenceQueue?q)?{

super(referent,?q);

}

也就是說,幽靈引用只能與ReferenceQueue(后面會提到這個類)一起使用。如果一個對象僅有幽靈引用,那么它就像沒有任何引用一樣,在任何時候都可能被gc回收。幽靈引用主要用來跟蹤對象被垃圾回收的活動。

Java代碼

publicclassPhantomTest{

publicstaticvoidmain(String[]?args)?{

Object?ref?=newObject();//ref是Object對象的強引用

//將一個幽靈引用指向對象,PhantomReference必須與ReferenceQueue一同使用

PhantomReference?pf?=newPhantomReference(ref,newReferenceQueue());

System.out.println(pf.get());

}

}

ReferenceQueue

如果一個對象只有軟引用、弱引用或者幽靈引用,gc在回收對象時,JVM會自動將其引用放入一個ReferenceQueue中。WeakHashMap就是利用了ReferenceQueue來實現清除沒有強引用Entry的。將上面的弱引用例子稍微改一下:

Java代碼

publicclassReferenceQueueTest{

publicstaticvoidmain(String[]?args)?{

Object?ref?=newObject();//ref是Object對象的強引用

System.out.println(ref);

ReferenceQueue?rq=newReferenceQueue();//有強引用的ReferenceQueue

WeakReference?sf?=newWeakReference(ref,rq);//構造弱引用時傳入ReferenceQueue

System.out.println(sf);

ref?=null;//去除對象的強引用,在這里加個斷點,進行調試

System.gc();//gc對弱引用對象進行回收

System.out.println(rq.poll());

}

}

注意,運行這個程序需要用debug模式進行調試,在上面說明的地方加個斷點。如果直接運行,結果很可能只是個null,用debug調試的話會看到輸出的是弱引用的地址。程序輸出的sf結果和rq.poll()結果相同。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容