示例代码如下:
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
/**
* @author chenjc
* @since 2020-01-13
*/
public class PhantomReferenceTest {
public static void main(String[] args) throws InterruptedException {
User user = new User(1, "debo");
ReferenceQueue<User> userReferenceQueue = new ReferenceQueue<>();
// 建立User对象的虚引用
PhantomReference<User> phantomReference = new PhantomReference<>(user, userReferenceQueue);
// 去掉强引用
user = null;
System.out.println(phantomReference.get());
// 手动触发GC
System.gc();
System.out.println("GC: " + phantomReference.get());
Reference<? extends User> reference = userReferenceQueue.remove(1000);
if (reference != null) {
System.out.println("对象User被回收了");
}
}
private static class User {
private Integer id;
private String name;
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
}
输出如下:
null
GC: null
对象User被回收了
可以发现,在GC之前调用phantomReference.get()也无法获得User对象,虚引用就和没有引用一样。那么虚引用存在的意义是什么呢?当GC准备回收对象时,如果发现该对象存在虚引用,就会在回收对象后,将这个虚引用加入引用队列,以通知应用程序对象回收情况,所以也可以将一些资源释放和记录操作放到虚引用中执行。