哪些Java案例展示了弱引用?

wen java案例 3

本文目录导读:

哪些Java案例展示了弱引用?

  1. 案例1:WeakHashMap——自动清理的缓存
  2. 案例2:WeakReference + ReferenceQueue——对象回收监听
  3. 案例3:Android 中的 AsyncDrawable 使用弱引用避免内存泄漏
  4. 案例4:自定义弱引用缓存(适合内存敏感场景)

在Java中,弱引用(WeakReference)最常见的应用场景是缓存避免内存泄漏,下面通过几个经典案例来说明。


案例1:WeakHashMap——自动清理的缓存

这是最经典的弱引用应用。WeakHashMap 的键使用弱引用,当键对象不再被外部强引用时,GC 会自动回收键,对应的键值对也会被自动移除。

import java.util.WeakHashMap;
import java.util.Map;
public class WeakHashMapDemo {
    public static void main(String[] args) {
        Map<Object, String> cache = new WeakHashMap<>();
        // 创建一个键对象
        Object key = new Object();
        cache.put(key, "some data");
        System.out.println("Before GC: " + cache.size());  // 1
        // 取消强引用
        key = null;
        // 触发 GC
        System.gc();
        // 等待 GC 完成(建议等待一小段时间)
        try { Thread.sleep(100); } catch (InterruptedException e) {}
        System.out.println("After GC: " + cache.size());   // 0(已被自动清理)
    }
}

输出(取决于 JVM 和 GC 时机,但通常类似):

Before GC: 1
After GC: 0

核心思想:当外部不再强引用 key 时,WeakHashMap 中的条目自动消失,避免了缓存无限膨胀。


案例2:WeakReference + ReferenceQueue——对象回收监听

这个案例展示了如何监控对象被 GC 回收的时刻,常用于资源清理或对象生命周期追踪。

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
class HeavyResource {
    // 模拟占用大量内存的资源
    private byte[] data = new byte[10 * 1024 * 1024]; // 10MB
}
public class WeakReferenceWithQueueDemo {
    public static void main(String[] args) throws InterruptedException {
        ReferenceQueue<HeavyResource> queue = new ReferenceQueue<>();
        HeavyResource resource = new HeavyResource();
        WeakReference<HeavyResource> weakRef = new WeakReference<>(resource, queue);
        System.out.println("Before GC: " + weakRef.get());  // 非空
        // 取消强引用
        resource = null;
        // 触发 GC
        System.gc();
        // 检查队列,看对象是否已被回收
        System.out.println("Reference queued: " + (queue.poll() != null));  // true(可能延迟)
        Thread.sleep(100);
        System.out.println("After GC: " + weakRef.get());   // null(已被回收)
    }
}

输出

Before GC: HeavyResource@...
Reference queued: true
After GC: null

核心思想:通过 ReferenceQueue 得知对象何时被回收,可用于执行后续清理或通知。


案例3:Android 中的 AsyncDrawable 使用弱引用避免内存泄漏

这是 Android 开发中的经典实践,当异步任务持有 Activity 或 View 的引用时,很容易造成内存泄漏,使用弱引用可以避免。

public class ImageLoader {
    // 回调接口,内部使用弱引用持有宿主
    public static class LoadCallback extends WeakReference<ImageView> {
        public LoadCallback(ImageView imageView) {
            super(imageView);
        }
        public void onLoadSuccess(Bitmap bitmap) {
            ImageView imageView = get();  // 获取弱引用的对象
            if (imageView != null) {
                imageView.setImageBitmap(bitmap);
            }
            // imageView 已被销毁(get 返回 null),则什么都不做
        }
    }
    public void loadImage(String url, ImageView imageView) {
        LoadCallback callback = new LoadCallback(imageView);
        // 异步加载图片...
        // 加载完成后调用 callback.onLoadSuccess(bitmap)
    }
}

核心思想LoadCallback 并不强持有 ImageView,当 Activity 被销毁时,ImageView 不再被强引用,GC 可以回收它,即使异步任务还在后台运行,也不会阻止 ImageView 的内存释放,从而避免泄漏。


案例4:自定义弱引用缓存(适合内存敏感场景)

如果希望自己实现一个缓存,当内存紧张时自动释放部分数据,可以使用 WeakReference 包装值对象。

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
public class WeakValueCache<K, V> {
    private final Map<K, WeakReference<V>> cache = new HashMap<>();
    public void put(K key, V value) {
        cache.put(key, new WeakReference<>(value));
    }
    public V get(K key) {
        WeakReference<V> ref = cache.get(key);
        if (ref == null) {
            return null;
        }
        V value = ref.get();
        if (value == null) {
            // 已被 GC 回收,从缓存中移除
            cache.remove(key);
        }
        return value;
    }
}

使用示例

WeakValueCache<String, Object> cache = new WeakValueCache<>();
String key = "id_123";
Object data = new Object();
cache.put(key, data);
// data 还被强引用,可以获取到
System.out.println(cache.get(key));  // 非空
data = null;  // 取消强引用
System.gc();
// 此时缓存可能已被 GC 清理
System.out.println(cache.get(key));  // 可能为 null

案例 使用方式 解决什么问题
WeakHashMap 键使用弱引用 缓存自动清理,防止内存泄漏
WeakReference + ReferenceQueue 对象引用 + 回收监听 跟踪对象生命周期,触发清理操作
Android AsyncDrawable 回调中弱引用宿主 避免异步任务导致 Activity 泄漏
自定义弱引用缓存 值使用弱引用 内存敏感场景下的自动释放

核心结论:弱引用的本质是“允许对象在没有强引用时被 GC 回收”,常用于缓存观察者模式回调等场景,防止内存泄漏。

抱歉,评论功能暂时关闭!