在 Java 中,对象引用分为四种类型:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference) 和 虚引用(Phantom Reference)。它们的主要区别在于对象的垃圾回收行为和生命周期的不同。
1. 强引用 (Strong Reference)
定义
- 普通的对象引用。
- 只要有强引用指向一个对象,该对象就不会被垃圾回收。
1. 强引用 (Strong Reference)
定义
- 普通的对象引用。
- 只要有强引用指向一个对象,该对象就不会被垃圾回收
场景
- 普通的业务对象。
- 假设我们正在处理用户的购物车,购物车对象应该始终存在于内存中,直到明确不需要它。
示例
public class ShoppingCart {
private List<String> items;
public ShoppingCart() {
items = new ArrayList<>();
}
public void addItem(String item) {
items.add(item);
}
public List<String> getItems() {
return items;
}
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart(); // 强引用
cart.addItem("Laptop");
cart.addItem("Mouse");
System.out.println(cart.getItems()); // 方法执行完之前不会被垃圾回收
}
}
特点
- 最常见的引用类型。
- 即使内存不足,垃圾回收器也不会回收强引用指向的对象,可能导致
OutOfMemoryError。
2. 软引用 (Soft Reference)
定义
- 在内存不足时,垃圾回收器会回收软引用指向的对象。
- 适合实现缓存机制。
场景
- 图片缓存。
- 在内存充足时,图片缓存不会被清理;当内存不足时,优先清理缓存,释放内存。
示例
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
public class ImageCache {
private final Map<String, SoftReference<byte[]>> imageCache = new HashMap<>();
public void putImage(String key, byte[] imageData) {
imageCache.put(key, new SoftReference<>(imageData));
}
public byte[] getImage(String key) {
SoftReference<byte[]> ref = imageCache.get(key);
return ref != null ? ref.get() : null; // 如果缓存被回收,返回 null
}
public static void main(String[] args) {
ImageCache cache = new ImageCache();
byte[] largeImage = new byte[10 * 1024 * 1024]; // 10MB 图片
cache.putImage("image1", largeImage);
System.out.println("Image loaded: " + (cache.getImage("image1") != null));
System.gc(); // 手动触发垃圾回收
System.out.println("After GC, Image loaded: " + (cache.getImage("image1") != null));
}
}
特点
- 在内存充足时,软引用的对象不会被回收。
- 当内存不足时,垃圾回收器会清理软引用,释放内存。
- 适合用于缓存较大的对象(如图片、结果集)。
3. 弱引用 (Weak Reference)
定义
- 无论内存是否充足,只要垃圾回收器运行,就会回收弱引用指向的对象。
- 常用于 WeakHashMap 等数据结构。
场景
- 弱引用映射(WeakHashMap)。
- 用于存储临时数据,比如存储和用户会话相关的配置信息。如果用户会话结束(强引用消失),数据会自动从映射中清除,避免内存泄漏。
示例
import java.util.Map;
import java.util.WeakHashMap;
public class WeakReferenceExample {
public static void main(String[] args) {
Map<Object, String> sessionData = new WeakHashMap<>();
Object sessionKey = new Object(); // 使用弱引用作为键
sessionData.put(sessionKey, "User Preferences");
System.out.println("Before GC: " + sessionData);
sessionKey = null; // 去除强引用
System.gc(); // 手动触发垃圾回收
System.out.println("After GC: " + sessionData); // 数据被清理
}
}
特点
- 即使对象正在使用,只要没有强引用或软引用指向它,也可能会被回收。
- 适合用来管理无需长时间存活的对象。
4. 虚引用 (Phantom Reference)
定义
- 不能通过虚引用获取对象。
- 用于跟踪对象的垃圾回收状态。
场景
- 监控对象的回收。
- 用于清理资源(如文件、数据库连接)。在对象即将被垃圾回收时,通过
ReferenceQueue获取通知,并执行清理操作。
示例
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class PhantomReferenceExample {
public static void main(String[] args) throws InterruptedException {
ReferenceQueue<Object> refQueue = new ReferenceQueue<>();
Object resource = new Object(); // 需要监控的资源
PhantomReference<Object> phantomRef = new PhantomReference<>(resource, refQueue);
System.out.println("Before GC: " + phantomRef.isEnqueued());
resource = null; // 去除强引用
System.gc(); // 手动触发垃圾回收
// 等待资源被回收
Thread.sleep(100);
System.out.println("After GC: " + phantomRef.isEnqueued()); // 是否已加入队列
if (refQueue.poll() != null) {
System.out.println("Resource is ready for cleanup!");
// 执行资源清理逻辑,例如关闭文件、断开数据库连接等。
}
}
}
特点
- 必须与
ReferenceQueue一起使用。 - 虚引用的主要作用是对象被垃圾回收前进行一些清理工作(如资源释放)。
- 虚引用的
get()方法永远返回null。
对比总结
| 引用类型 | 描述 | 是否被回收的条件 | 适用场景 |
|---|---|---|---|
| 强引用 | 普通对象引用,默认引用类型 | 永远不会被回收 | 核心逻辑和对象的正常使用。 |
| 软引用 | 在内存不足时可回收的引用 | 内存不足时回收 | 缓存对象。 |
| 弱引用 | 弱化的引用,随时可能被回收 | GC 扫描到时回收 | 临时性对象或映射。 |
| 虚引用 | 不存活的引用,用于跟踪对象回收 | 对象即将被回收时回收,并在 ReferenceQueue 中通知 | 资源释放或清理。 |
544

被折叠的 条评论
为什么被折叠?



