看了那么多关于软引用,弱引用,虚引用的例子,还是从源码开始说起为什么可以这样做吧
软引用 SoftReference
/**
* Timestamp clock, updated by the garbage collector
*/
static private long clock;
/**
* Timestamp updated by each invocation of the get method. The VM may use
* this field when selecting soft references to be cleared, but it is not
* required to do so.
*/
private long timestamp;
与Reference类相比多了两个参数,clock由gc维护,timestamp由虚拟机维护,每次调用更新timestamp
public SoftReference(T referent) {
super(referent);
this.timestamp = clock;
}
public SoftReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
this.timestamp = clock;
}
采用了两种初始化的方式,在构造函数中设置了timestamp的值
public T get() {
T o = super.get();
if (o != null && this.timestamp != clock)
this.timestamp = clock;
return o;
}
测试代码
SoftReference<String> sr = new SoftReference<String>(
new String("hello"));
System.out.println(sr.get());
System.gc();
System.out.println(sr.get());
测试结果
hello
hello
get方法首先调用了父类方法获得返回对象,然后修改了timestamp的值为每次调用的时间
在System.gc()调用后,依然可以获取对象的值
弱引用 WeakReference
public WeakReference(T referent) {
super(referent);
}
public WeakReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}
测试代码
WeakReference<String> sr = new WeakReference<String>(
new String("hello"));
System.out.println(sr.get());
System.gc(); // 通知JVM的gc进行垃圾回收
System.out.println(sr.get());
测试结果
hello
null
弱引用继承了Reference类,实现了两种自己的初始化,其他的方法使用Reference的方法,因此,在System.gc()后输出结果为null
虚引用 PhantomReference
不影响对象生命周期
* <p> Unlike soft and weak references, phantom references are not
* automatically cleared by the garbage collector as they are enqueued. An
* object that is reachable via phantom references will remain so until all
* such references are cleared or themselves become unreachable.
从javadoc可以看出来,虚引用不会自动被gc清理,需要相关引用全部清除,或是引用自身不可达的时候才可以被清除
public T get() {
return null;
}
public PhantomReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}
从源代码可以看到,PhantomReference继承了Reference类,初始化的时候把引用添加进了引用队列,在调用get()方法的时候固定返回一个null值
测试代码
ReferenceQueue<String> queue = new ReferenceQueue<String>();
PhantomReference<String> pr = new PhantomReference<String>(new String(
"hello"), queue);
System.out.println(pr.get());
输出结果
null
因此,不经过System.gc(),每次返回的就是一个null