学习整理——Java四种引用类型

来源:互联网 发布:南昌金域名都 开发商 编辑:程序博客网 时间:2024/06/10 17:26

参考:http://www.pocketcn.com/forum-viewthread-tid-1661-fromuid-1477.html


从jdk1.2开始,Java把对象引用分为四个等级——强引用、软引用、弱引用、虚引用,每一种引用都有其应用的地方,提供高度灵活性给程序。


强引用

实际程序当中,强引用是使用最普遍的。一个对象拥有强引用,垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题,保证后续程序的正确性。

通过声明一个引用变量并指定它所引用的对象的方式就是强引用:A a1 = new A(); A a2 = a1;

import java.util.*;public class ReferenceTest {public static void main(String[] args){Test test = new Test();test = null;try {System.gc();Thread.sleep(10000);} catch (Exception e) {e.printStackTrace();}}}class Test {public Test(){    System.out.println("Created at " + System.currentTimeMillis());}@Override  public void finalize(){    System.out.println("Instance is destroyed by system at " + System.currentTimeMillis());    }  }
程序使用强引用引用一个对象,然后将变量置为null,向系统请求gc。由于对象没有任何引用,一旦执行gc,该对象将被回收。

输出

Created at 1473734462128Instance is destroyed by system at 1473734462160

软引用

如果一个对象只具有(如果还具有强引用则不在此讨论范围)软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。也就是说,软引用为那些失去了强引用的对象提供一个相对安全的保障,只有内存空间充足,这些对象可以继续存在。由此可见,软引用可以用于一些缓存的应用环境当中。

使用软引用使用SoftReference;

SoftReference<T> softRefernce = new SoftReference<T>(t);   // 将对象引用赋值给一个软引用

T t1 = (T) softReference.get();  // 返回一个强引用,若对象因内存告急被回收,则返回null 

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。 由于软引用对象也是对象,当它所软引用的对象被回收之后,该软引用失去了存在性,该软引用对象应当也被处理掉。

ReferenceQueue queue = new ReferenceQueue();   // 软引用队列
SoftReference ref = new SoftReference(aMyObject, queue);   //  将队列的引用加入到软引用对象的构造函数参数中


// 处理没有存在性的软引用对象

SofeReference softReference = null;

while((softReference = queue.poll())!=null){

   //  此时在该队列里面的软引用对象所引用的对象已被gc回收 

   //  相应操作

}


在上面代码的基础上加入软引用

<span style="white-space:pre"></span>public static void main(String[] args){Test test = new Test();SoftReference<Test> softReference = new SoftReference<Test>(test);   // 将对象加入软引用test = null;try {System.gc();Thread.sleep(10000);} catch (Exception e) {e.printStackTrace();}}
输出

Created at 1473736268577


弱引用

弱引用与软引用类似,主要区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。使用弱引用,可以让对象在不添加新的强引用(添加强引用会阻碍正常gc)的情况下在某些地方能够返回出它的引用,可以像正常流程一样被系统管理。如WeakHashMap,value何map之间是一种很弱的关系,当value在外部不再存在时,map便不能把它找到。

弱引用使用WeakReference,用法与SoftReference类似。

弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。


将上述代码的软引用改为弱引用

public static void main(String[] args){Test test = new Test();//SoftReference<Test> softReference = new SoftReference<Test>(test);   // 将对象加入软引用WeakReference<Test> weakReference = new WeakReference<Test>(test);   // 将对象加入弱引用test = null;try {System.gc();Thread.sleep(10000);} catch (Exception e) {e.printStackTrace();}}

输出

Created at 1473737483154Instance is destroyed by system at 1473737483169


虚引用

虚引用,顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。

虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。

有意思的是,PhantomReference 源码中显示了get()方法永远返回null

public class PhantomReference<T> extends Reference<T> {    /**     * Returns this reference object's referent.  Because the referent of a     * phantom reference is always inaccessible, this method always returns     * <code>null</code>.     *     * @return  <code>null</code>     */    public T get() {        return null;    }    /**     * Creates a new phantom reference that refers to the given object and     * is registered with the given queue.     *     * <p> It is possible to create a phantom reference with a <tt>null</tt>     * queue, but such a reference is completely useless: Its <tt>get</tt>     * method will always return null and, since it does not have a queue, it     * will never be enqueued.     *     * @param referent the object the new phantom reference will refer to     * @param q the queue with which the reference is to be registered,     *          or <tt>null</tt> if registration is not required     */    public PhantomReference(T referent, ReferenceQueue<? super T> q) {        super(referent, q);    }}
所以主要还是用于跟踪对象被回收情况。


0 0
原创粉丝点击