WeakReference是手动管理的单对象弱引用工具,需判空、维护强引用并处理ReferenceQueue;WeakHashMap是自动清理的弱键Map容器,键被GC后条目惰性移除,无需手动干预。

WeakReference 和 WeakHashMap 都基于弱引用机制,但它们在缓存变量时的职责、使用方式和管理粒度完全不同——前者是底层引用工具,后者是开箱即用的缓存容器。
WeakReference 是手动控制的“弱连接”
它不提供任何集合行为,只负责单个对象的弱持有。你需要自己维护引用生命周期、判断是否存活、处理 null 值,并配合 ReferenceQueue 主动轮询或清理引用对象本身。
- 每次 get() 都要判空:若返回 null,说明对象已被 GC,不能再用
- 必须显式保存对原始对象的强引用(否则一创建就可能被回收)
- 若注册了 ReferenceQueue,还需额外逻辑 poll/清理队列中的 WeakReference 实例,否则这些引用对象本身会堆积内存
- 适合场景:监听器解耦、临时代理、需要精细控制回收时机的单点缓存
WeakHashMap 是自动管理的“弱键缓存”
它把 WeakReference 封装进内部 Entry,并绑定 ReferenceQueue,在每次访问(get/put/size 等)时自动清理已回收键对应的条目。你只需当它是 Map 用,无需关心 GC 时机或队列轮询。
- 键(key)是弱引用,值(value)仍是强引用 —— 所以只有 key 被回收才会触发整条 entry 移除
- entry 清理不是实时的,而是在下一次调用 size()/get()/nextEntry() 等方法时惰性触发(通过 expungeStaleEntries())
- 不能用来缓存“只靠 value 维持生命周期”的对象;若需 value 也弱化,得自行包装成 WeakReference<V>
- 适合场景:短期会话映射、监听器注册表、类加载器关联缓存等 key 易失效、且不希望内存泄漏的场合
关键差异对比:谁管什么?
WeakReference 管“一个对象能不能活”,WeakHashMap 管“一个键值对该不该留”。前者是原子能力,后者是封装策略。
- WeakReference 不知道 map、不涉及哈希、不处理冲突,它只是个带队列支持的指针
- WeakHashMap 内部每个 key 都是一个 WeakReference<K>,但它还承担了哈希桶管理、扩容、迭代安全、并发控制(非线程安全,需外层同步)等完整 Map 职责
- 直接用 WeakReference 做缓存,容易漏掉引用对象本身的清理;用 WeakHashMap,则天然规避了这一风险(entry 清理包含引用对象释放)
什么时候选哪个?
想快速上线一个轻量、自清理、key 生命周期由业务决定的缓存?WeakHashMap 更稳妥。想精确控制某个资源的释放钩子、或实现自定义回收策略(比如结合软引用+弱引用分层)?从 WeakReference 开始构建更灵活。
- 缓存用户界面组件(如 View → Handler 映射),key 是 Activity,用 WeakHashMap 可防泄漏
- 实现一个带过期通知的单例资源代理,需在 GC 前执行 close(),就得用 WeakReference + ReferenceQueue 回调
- 做分代缓存(eden + longterm),WeakHashMap 适合作为 longterm 层,而 eden 用 ConcurrentHashMap —— 这正是 Tomcat 缓存的设计思路

















