让我用生活中的例子来解释这四种引用:
- 强引用(Strong Reference)- 就像你的必需品:
// 就像你非常需要的钱包,不会丢弃
public class StrongReferenceExample {
public void strongReference() {
// 强引用 - 你正在使用的钱包
Object wallet = new Object();
// wallet变量指向对象的引用永远不会被垃圾回收器回收
// 即使内存不足,也不会回收
System.gc(); // 垃圾回收不会回收wallet对象
}
}
- 软引用(Soft Reference)- 就像备用物品:
// 就像家里的备用手机,如果实在需要空间可以扔掉
public class SoftReferenceExample {
public void softReference() {
// 创建一个图片缓存
SoftReference<ImageCache> imageCache =
new SoftReference<>(new ImageCache());
// 使用缓存
if (imageCache.get() != null) {
// 缓存还在,可以使用
imageCache.get().displayImage();
} else {
// 缓存被回收了,需要重新加载
reloadCache();
}
}
}
// 实际应用:图片缓存
public class ImageCacheManager {
private Map<String, SoftReference<Bitmap>> imageCache =
new HashMap<>();
public void cacheImage(String url, Bitmap bitmap) {
imageCache.put(url, new SoftReference<>(bitmap));
}
public Bitmap getImage(String url) {
SoftReference<Bitmap> bitmapRef = imageCache.get(url);
if (bitmapRef != null) {
Bitmap bitmap = bitmapRef.get();
if (bitmap != null) {
return bitmap;
}
// 软引用对象被回收,从imageCache中移除
imageCache.remove(url);
}
return null;
}
}
- 弱引用(Weak Reference)- 就像借来的东西:
// 就像借来的书,随时可能要还
public class WeakReferenceExample {
public void weakReference() {
// 创建一个弱引用
WeakReference<DataCache> dataCache =
new WeakReference<>(new DataCache());
// 使用WeakHashMap存储数据
WeakHashMap<Key, Data> cache = new WeakHashMap<>();
cache.put(new Key("1"), new Data("data1"));
// 一旦没有其他强引用指向Key对象
// WeakHashMap中的对应条目就可能被回收
System.gc(); // 可能触发回收
}
}
// 实际应用:防止内存泄漏的监听器管理
public class ListenerManager {
private List<WeakReference<EventListener>> listeners =
new ArrayList<>();
public void addListener(EventListener listener) {
listeners.add(new WeakReference<>(listener));
}
public void notifyListeners(Event event) {
Iterator<WeakReference<EventListener>> iterator =
listeners.iterator();
while (iterator.hasNext()) {
WeakReference<EventListener> listenerRef = iterator.next();
EventListener listener = listenerRef.get();
if (listener != null) {
listener.onEvent(event);
} else {
// 监听器对象已被回收,移除引用
iterator.remove();
}
}
}
}
- 虚引用(Phantom Reference)- 就像快递追踪:
// 就像快递的追踪单,不影响快递的派送,只用来追踪状态
public class PhantomReferenceExample {
public void phantomReference() {
// 创建引用队列
ReferenceQueue<BigObject> referenceQueue =
new ReferenceQueue<>();
// 创建虚引用
PhantomReference<BigObject> phantomRef =
new PhantomReference<>(
new BigObject(),
referenceQueue
);
// 检查对象是否被回收
new Thread(() -> {
try {
Reference<?> reference = referenceQueue.remove();
// 对象被回收了,执行清理操作
System.out.println("对象被回收");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
// 实际应用:资源清理
public class ResourceTracker {
private ReferenceQueue<Resource> queue = new ReferenceQueue<>();
private List<PhantomReference<Resource>> references =
new ArrayList<>();
public void track(Resource resource) {
references.add(new PhantomReference<>(resource, queue));
}
public void cleanUp() {
Reference<?> ref;
while ((ref = queue.poll()) != null) {
// 执行清理操作
((ResourcePhantomReference)ref).cleanup();
references.remove(ref);
}
}
}
实际使用场景对比:
- 缓存实现:
public class CacheManager {
// 强引用缓存 - 永不释放
private Map<String, Object> strongCache =
new HashMap<>();
// 软引用缓存 - 内存不足时释放
private Map<String, SoftReference<Object>> softCache =
new HashMap<>();
// 弱引用缓存 - 垃圾回收时释放
private Map<String, WeakReference<Object>> weakCache =
new WeakHashMap<>();
// 根据不同场景使用不同缓存
public void putIntoCache(String key, Object value, CacheType type) {
switch (type) {
case STRONG:
strongCache.put(key, value);
break;
case SOFT:
softCache.put(key, new SoftReference<>(value));
break;
case WEAK:
weakCache.put(key, new WeakReference<>(value));
break;
}
}
}
使用建议:
-
使用强引用当:
- 对象是必需的
- 不希望对象被垃圾回收
-
使用软引用当:
- 实现内存敏感的缓存
- 对象可以被回收但最好保留
-
使用弱引用当:
- 实现规范化映射
- 防止内存泄漏
-
使用虚引用当:
- 跟踪对象的回收
- 需要在对象回收时执行特定操作
它们就像生活中对待不同物品的态度:
- 强引用:必需品(钱包)
- 软引用:备用品(备用手机)
- 弱引用:借来的物品(图书馆的书)
- 虚引用:追踪记录(快递单号)