Java中的Reference类体系定义了四种不同的引用类型,分别是强引用、软引用、弱引用和虚引用,它们在垃圾回收时的处理规则不同,直接决定了对象的存活时间,是内存优化的重要基础知识点。

强引用
强引用是日常开发中最常用的引用类型,我们平时通过new关键字创建的对象关联的都是强引用。只要强引用存在,垃圾回收器就不会回收被引用的对象,哪怕内存空间不足时,JVM也会优先抛出OutOfMemoryError,而不会回收强引用指向的对象。
强引用示例
public class StrongReferenceDemo {
public static void main(String[] args) {
// 创建强引用,obj指向新创建的Object对象
Object obj = new Object();
// 此时obj是强引用,垃圾回收器不会回收该Object对象
System.gc();
// 即使手动触发GC,obj指向的对象也不会被回收
System.out.println(obj != null); // 输出true
// 断开强引用
obj = null;
// 此时对象没有强引用指向,下次GC时会被回收
System.gc();
}
}
软引用
软引用通过SoftReference类实现,当内存空间充足时,软引用指向的对象不会被回收;只有当内存空间不足,即将发生OutOfMemoryError时,垃圾回收器才会回收软引用指向的对象。这种特性让软引用非常适合用于实现内存敏感的缓存场景。
软引用示例
import java.lang.ref.SoftReference;
public class SoftReferenceDemo {
public static void main(String[] args) {
// 创建软引用,指向一个大小为10MB的字节数组
SoftReference<byte[]> softRef = new SoftReference<>(new byte[10 * 1024 * 1024]);
// 内存充足时,软引用对象不会被回收
System.out.println(softRef.get() != null); // 输出true
// 尝试分配大内存,触发内存不足
try {
byte[] bigArray = new byte[20 * 1024 * 1024];
} catch (OutOfMemoryError e) {
// 内存不足时,软引用指向的对象会被回收
System.out.println(softRef.get() == null); // 输出true
}
}
}
弱引用
弱引用通过WeakReference类实现,弱引用的生命周期比软引用更短,只要垃圾回收器扫描到弱引用指向的对象,不管当前内存是否充足,都会回收该对象。弱引用常用来实现一些临时关联的场景,避免内存泄漏。
弱引用示例
import java.lang.ref.WeakReference;
public class WeakReferenceDemo {
public static void main(String[] args) {
// 创建弱引用
WeakReference<Object> weakRef = new WeakReference<>(new Object());
// 触发一次GC
System.gc();
// 弱引用指向的对象会被回收
System.out.println(weakRef.get() == null); // 输出true
}
}
WeakHashMap就是基于弱引用实现的,它的key是弱引用,当key没有其他强引用指向时,对应的键值对会在GC时被自动移除,避免内存泄漏。
虚引用
虚引用通过PhantomReference类实现,它是最弱的一种引用类型,虚引用完全不会影响对象的生命周期,也无法通过虚引用获取到对象实例。虚引用的主要作用是在对象被垃圾回收时收到一个系统通知,通常用来跟踪对象被垃圾回收的状态。
虚引用示例
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class PhantomReferenceDemo {
public static void main(String[] args) {
Object obj = new Object();
// 创建引用队列
ReferenceQueue<Object> queue = new ReferenceQueue<>();
// 创建虚引用,关联引用队列
PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue);
// 无法通过虚引用获取对象
System.out.println(phantomRef.get() == null); // 输出true
// 断开强引用
obj = null;
// 触发GC
System.gc();
// 虚引用指向的对象被回收后,虚引用会被加入引用队列
System.out.println(queue.poll() == phantomRef); // 输出true
}
}
四种引用对比
四种引用的核心差异可以通过以下表格清晰展示:
| 引用类型 | 实现类 | 回收时机 | 典型应用场景 |
|---|---|---|---|
| 强引用 | 无 | 只要引用存在,永不回收 | 普通对象关联 |
| 软引用 | SoftReference | 内存不足时回收 | 内存敏感缓存 |
| 弱引用 | WeakReference | GC时必然回收 | 临时关联、WeakHashMap |
| 虚引用 | PhantomReference | GC时回收,触发通知 | 跟踪对象回收状态 |
使用注意事项
- 强引用要避免不必要的长生命周期持有,否则容易导致内存泄漏。
- 使用软引用和弱引用时,要注意判断
get()方法返回的结果是否为null,因为对象可能已经被回收。 - 虚引用必须和引用队列配合使用,否则无法感知对象的回收状态。
Reference类体系强引用软引用弱引用虚引用修改时间:2026-06-26 00:15:54