四种引用的区别在于GC回收时机:强引用需断开所有引用才回收;软引用在内存不足时回收,适合缓存;弱引用每次GC都可能回收,用于WeakHashMap等;虚引用不阻止回收,仅通过ReferenceQueue通知对象即将被回收。

区分这四种引用的关键,在于它们被垃圾回收器(GC)处理的时机和条件,而不是写法有多复杂。核心差异就落在“GC 什么时候、什么条件下会把它指向的对象收走”上。
强引用:只要它还连着,GC 绝不碰
这是默认的引用方式,比如 Object obj = new Object()。只要栈里这个 obj 变量还有效(没设为 null、没出作用域),堆里的对象就永远不会被回收。哪怕内存快爆了,JVM 宁愿抛 OutOfMemoryError,也不会动它。
- 回收前提:必须先断开所有强引用(例如显式赋值为 null 或变量自然失效)
- 典型风险:静态集合长期持有强引用,容易导致内存泄漏
软引用:内存告急时才清理,适合缓存
用 SoftReference<T> 包一层,对象就变成“可牺牲但优先保”的状态。GC 会尽量留着它,直到真正判断“再不回收就要 OOM”了,才会动手。
- 回收触发点:JVM 认为内存不足(通常在 Full GC 前做一次内存压力评估)
- 特点:比弱引用“命长”,比强引用“松动”,天然适合图片、数据等缓存场景
- 注意:不能保证一定等到内存不足才回收,某些 GC 算法(如 G1)可能更激进
弱引用:GC 扫到就清,不讲情面
用 WeakReference<T> 包裹后,对象就进入“朝生暮死”状态。只要某次 GC 运行时扫描到了它,不管内存多富裕,立刻回收。
- 回收时机:任意一次 GC(尤其是 Young GC)都可能触发
- 典型用途:WeakHashMap 的 key、ThreadLocalMap 的 key,防止因引用滞留导致内存泄漏
- 小细节:即使对象重写了 finalize(),弱引用也只在第一次 GC 标记后入队,不阻塞回收流程
虚引用:不拦回收,只发通知
用 PhantomReference<T> 必须搭配 ReferenceQueue 使用。它无法通过 get() 拿到对象(永远返回 null),唯一作用是——当对象被 GC 决定回收的瞬间,把这个虚引用推送到队列里,让你知道“它要没了”。
- 回收行为:对象仅剩虚引用时,等同于无引用,GC 随时可回收
- 核心价值:做资源清理钩子,比如关闭文件句柄、释放堆外内存(配合 Cleaner)
- 硬性要求:不传 ReferenceQueue 就没意义,构造时必须指定

















