在 JDK 1.2 以前,Java 中的引用的定义很传统:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用。
这种定义很纯粹,但是太过于狭隘,一个对象在这种定义下只有被引用或者没有被引用两种状态,对于如何描述一些 “食之无味,弃之可惜” 的对象就显得无能为力。
在 JDK 1.2 之后,Java 对引用的概念进行了扩充,将引用扩充为如下四种:
- 强引用
- 软引用
- 弱引用
- 虚引用
强度为:强引用 > 软引用 > 弱引用 > 虚引用
接下来,我们依次看一下这四种强度的引用。
1. 强引用
最普遍的引用,比如Object obj = new Object();
,其中 obj 就是强引用。
换句话说,使用 new 一个新对象的方式就是创建了强引用。
被强引用关联的对象不会被回收,Java 虚拟机宁可抛出 OutOfMemoryError 也不肯将其回收,如果想将被强引用关联的对象回收掉,可以这样:obj = null;
弱化其引用。
2. 软引用
软引用用来描述一些还有用但并非必需的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。
可以用来实现高速缓存。
使用 SoftReference 类来创建软引用。
Object obj = new Object(); // 强引用
SoftReference<Object> sf = new SoftReference<Object>(obj); // 软引用
obj = null; // 使对象只被软引用关联
3. 弱引用
弱引用也是用来描述一些非必需的对象的,不过强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。
使用 WeakReference 类来创建弱引用。
Object obj = new Object(); // 强引用
WeakReference<Object> wf = new WeakReference<Object>(obj); // 弱引用
obj = null; // 使对象只被软引用关联
4. 虚引用
又称为幽灵引用或者幻影引用,最弱的一种引用关系,弟中弟。
一个对象是否有虚引用的存在,不会对其生存时间造成影响,也无法通过虚引用得到一个对象。
为一个对象设置虚引用的唯一目的是能在这个对象被回收时收到一个系统通知,换句话说这就是起到了一个哨兵的作用。
使用 PhantomReference 来创建虚引用。
Object obj = new Object(); // 强引用
PhantomReference<Object> pf = new PhantomReference<Object>(obj, null); // 虚引用
obj = null; // 使对象只被软引用关联
用一个表格梳理一下这四种引用。