Java中四种引用类型定义对象存活语义:强引用永不回收;软引用在内存不足时回收,适合缓存;弱引用在每次GC时立即回收,用于临时映射;虚引用无法获取对象,仅配合引用队列通知回收,用于资源清理。

Java 中的四种引用类型——强引用、软引用、弱引用和虚引用——决定了垃圾回收器(GC)是否可以回收某个对象,以及在什么条件下回收。它们不是功能上的增强,而是对“对象存活与否”的不同语义定义。
强引用:最常用,不被 GC 回收
平时写的 Object obj = new Object() 就是强引用。只要这个引用还存在(且没被置为 null),对象就永远不会被 GC 回收,哪怕内存不足抛出 OutOfMemoryError,也不会动它。
说明:强引用是默认引用类型,也是开发中最常使用的。它不参与 JVM 的引用队列机制,也不影响 GC 策略。
软引用:内存紧张时才回收,适合缓存
用 SoftReference<T> 包装对象,例如:
SoftReference<byte[]> ref = new SoftReference<>(new byte[1024 * 1024]);
JVM 在发生 GC 时,会先尝试保留软引用对象;只有在即将发生内存溢出(即内存真的不够用了)时,才会回收所有软引用指向的对象。
建议:
• 适合做内存敏感型缓存(如图片缓存、查询结果缓存)
• 不要依赖软引用一定长期存活,它只是“尽量留着”
• 可配合引用队列(ReferenceQueue)监听对象是否已被回收
弱引用:GC 时立即回收,适合临时映射
用 WeakReference<T> 包装,例如:
WeakReference<String> ref = new WeakReference<>(new String("hello"));
只要发生一次 GC(哪怕是 Minor GC),该对象就会被回收,不管当前堆内存是否充足。
常见用途:
• ThreadLocal 中的 key 使用弱引用,防止内存泄漏
• WeakHashMap 的 key 是弱引用,避免 key 对象无法释放导致 map 持有其引用
• 构建非强制生命周期依赖的映射关系(如监听器注册表)
虚引用:唯一不能获取对象实例的引用,仅用于回收通知
用 PhantomReference<T> 包装,必须配合 ReferenceQueue 使用。它不能通过 get() 获取对象(始终返回 null),唯一作用是:当对象被 GC 回收后,JVM 会把该虚引用加入关联的引用队列,从而让程序感知“对象已死”。
关键点:
• 虚引用不会阻止对象被回收
• 必须与 ReferenceQueue 配合才能起作用
• 常用于实现更精细的资源清理逻辑(如堆外内存释放、文件句柄关闭),替代或补充 finalize() 方法(后者已被弃用)










