Java有四種引用類型,strongreference,softreference,weakreference,phantomreference。這四種引用的強度按照上面的順序依次減弱,下面通過幾個例子簡單了解一下這四種引用類型。
StrongReference
這個不用多講了,這是java默認(rèn)的引用類型,如果不特意使用java.lang.ref下的類,那么程序中的所有引用都是強引用。有強引用存在的對象永遠(yuǎn)都不會被gc收集,所以在內(nèi)存不夠用時,JVM寧愿拋出OutOfMemoryError這樣的錯誤,也不愿意將強引用對象進行回收。
SoftReference
軟引用不會保證對象一定不會被回收,只能最大可能保證。如果內(nèi)存有剩余,那么軟引用對象不會被回收,如果內(nèi)存不足,那么gc會回收軟引用對象。所以這種特性可以用來實現(xiàn)緩存技術(shù)。軟引用要用java.lang.ref.SoftReference來實現(xiàn)。

publicclassSoftTest{
publicstaticvoidmain(String[]?args)?{
Object?ref?=newObject();//ref是Object對象的強引用
//將一個軟引用指向?qū)ο?,此時Object對象有兩個引用
SoftReference?sf?=newSoftReference(ref);
ref?=null;//去除對象的強引用
System.gc();//gc只有在內(nèi)存不足是才會回收軟引用對象
}
}
WeakReference
除了通過java.lang.ref.WeakReference來使用弱引用,WeakHashMap同樣也利用了弱引用。
和軟引用不同的是,弱引用一定會被gc回收,不管內(nèi)存是否不足。

publicclassWeakTest{
publicstaticvoidmain(String[]?args)?{
Object?ref?=newObject();//ref是Object對象的強引用
//將一個弱引用指向?qū)ο螅藭rObject對象有兩個引用
WeakReference?wf?=newWeakReference(ref);
ref?=null;//去除對象的強引用
System.gc();//gc對弱引用對象進行回收
}
}
PhantomReference
幽靈引用,也叫虛引用。java.lang.ref.PhantomReference類中只有一個方法get(),而且?guī)缀鯖]有實現(xiàn),只是返回null。而且這個類只有一個構(gòu)造器(軟引用和弱引用均有兩個構(gòu)造器):

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

publicclassPhantomTest{
publicstaticvoidmain(String[]?args)?{
Object?ref?=newObject();//ref是Object對象的強引用
//將一個幽靈引用指向?qū)ο螅琍hantomReference必須與ReferenceQueue一同使用
PhantomReference?pf?=newPhantomReference(ref,newReferenceQueue());
System.out.println(pf.get());
}
}
ReferenceQueue
如果一個對象只有軟引用、弱引用或者幽靈引用,gc在回收對象時,JVM會自動將其引用放入一個ReferenceQueue中。WeakHashMap就是利用了ReferenceQueue來實現(xiàn)清除沒有強引用Entry的。將上面的弱引用例子稍微改一下:

publicclassReferenceQueueTest{
publicstaticvoidmain(String[]?args)?{
Object?ref?=newObject();//ref是Object對象的強引用
System.out.println(ref);
ReferenceQueue?rq=newReferenceQueue();//有強引用的ReferenceQueue
WeakReference?sf?=newWeakReference(ref,rq);//構(gòu)造弱引用時傳入ReferenceQueue
System.out.println(sf);
ref?=null;//去除對象的強引用,在這里加個斷點,進行調(diào)試
System.gc();//gc對弱引用對象進行回收
System.out.println(rq.poll());
}
}
注意,運行這個程序需要用debug模式進行調(diào)試,在上面說明的地方加個斷點。如果直接運行,結(jié)果很可能只是個null,用debug調(diào)試的話會看到輸出的是弱引用的地址。程序輸出的sf結(jié)果和rq.poll()結(jié)果相同。