WeakReference 的核心是切断不该存在的强引用链,而非提供弱保护;应将短生命周期对象用 WeakReference 包装后由长生命周期组件持有,避免内存泄漏。

WeakReference 本身不“配合类结构”,它配合的是引用关系的设计逻辑——关键不是类怎么写,而是谁持有谁、何时该断开、哪些引用不该阻止回收。用错地方不仅防不住内存溢出,反而让缓存失效、逻辑崩溃。
WeakReference 的真实作用:切断不该存在的强引用链
它不是给对象“加一层弱保护”,而是给本不该长期持有的引用套上一个“可随时放手”的外壳。典型场景里,问题出在类之间的隐式或显式强依赖上:
- 非静态内部类(如 Handler、Runnable)隐式持外部 Activity/Fragment,导致 Activity 无法被 GC
- View 或 Context 被注册为监听器的 target,而监听器又长期存活(比如在单例或静态容器中)
- ThreadLocal 的 value 是大对象,且线程复用(如线程池)时未 remove,value 一直被强引用挂着
- 用 Activity 或 Fragment 实例作 Map 的 key,但 Map 是静态或长生命周期的
怎么在类设计中嵌入 WeakReference
核心原则:把短生命周期对象的引用包进 WeakReference,再由长生命周期组件持有这个弱引用对象,而不是直接持有原对象。
- Handler 场景:定义静态内部类 Handler,并用 WeakReference
持有 Activity,避免隐式强引用 - 点击监听:封装 OnClickListener 时,传入 WeakReference
或 WeakReference ,每次 onClick 先 get() 再判空和状态 - 缓存 key 场景:不用 Activity 本身作 key,改用 WeakReference
作 key —— 更稳妥的做法是用 WeakHashMap,它的 key 天然弱引用 - ThreadLocal 场景:WeakReference 不用于包装 value,而是理解 ThreadLocalMap 的 key 本身就是弱引用;真正要做的,是在使用后调用 remove() 清掉 value 强引用
不能这么用:把 WeakReference 当缓存容器
例如:new WeakReference(new byte[1024*1024]) 放进 static Map——这等于主动放弃缓存有效性。因为:
立即学习“Java免费学习笔记(深入)”;
- GC 一触发,byte[] 立刻被回收,get() 返回 null
- 你无法控制回收时机,也无法做 LRU/LFU 淘汰
- 反复创建 WeakReference + put 进 map,反而增加 GC 压力
真要缓存,优先选 SoftReference(配合手动清理)或 LruCache(Android)/ Caffeine(后端),它们才具备缓存语义。
配合 ReferenceQueue 做主动清理(进阶)
当 WeakReference 所引用对象被回收,它自己会进入关联的 ReferenceQueue。你可以起一个轻量线程或在关键路径轮询队列,及时从 Map 中移除失效条目:
- 构造 WeakReference 时传入 new ReferenceQueue()
- 定期 poll 队列,拿到已回收的 WeakReference 对象
- 根据其 identity(如自定义 key 字段)清理外部容器中的对应项
这在监听器管理、资源映射表等需要“自动反注册”的场景中很实用,但日常开发中更推荐显式 remove(如 onDestroy() 里清 listener)。


















