Java 强引用、软引用、弱引用、虚引用:从入门到实战

在 Java 开发中,对象的引用类型直接影响内存管理和垃圾回收(GC)的行为。除了常见的强引用,Java 还提供了软引用(SoftReference)、弱引用(WeakReference)和虚引用(PhantomReference),用于实现更灵活的内存管理策略。本文将深入解析这四种引用类型,并通过多个代码示例展示其实际应用场景。

一、强引用(Strong Reference)

1. 基本概念

强引用是默认的引用类型,只要对象存在强引用,垃圾回收器就不会回收该对象。只有当强引用被显式置为 null 或超出作用域时,对象才会被标记为可回收。

Object obj = new Object(); // 强引用
obj = null; // 取消强引用,对象可被回收
2. 应用场景
  • 常规对象创建,如业务逻辑中的核心对象。

  • 需要长期驻留内存的数据(如配置信息)。

二、软引用(SoftReference)

1. 基本概念

软引用描述的对象在内存不足时会被回收。当 JVM 发现内存吃紧时,会清理软引用指向的对象。这种特性使得软引用非常适合实现内存敏感的缓存。

2. 代码示例:图片缓存
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

public class ImageCache {
    private Map<String, SoftReference<Bitmap>> cache = new HashMap<>();

    public Bitmap getImage(String key) {
        SoftReference<Bitmap> ref = cache.get(key);
        if (ref != null) {
            Bitmap bitmap = ref.get();
            if (bitmap != null) {
                return bitmap;
            }
        }
        // 重新加载图片
        Bitmap bitmap = loadImageFromDisk(key);
        cache.put(key, new SoftReference<>(bitmap));
        return bitmap;
    }

    private Bitmap loadImageFromDisk(String key) {
        // 模拟从磁盘加载图片
        return new Bitmap();
    }

    static class Bitmap {
        // 图片数据
    }
}

应用场景

  • 缓存图片、临时数据等,避免 OOM。

  • 需要内存不足时自动释放的非关键数据。

三、弱引用(WeakReference)

1. 基本概念

弱引用比软引用更弱,被弱引用关联的对象只能存活到下一次 GC。无论内存是否充足,弱引用对象都会被回收。

2. 代码示例:监听器列表
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

public class EventManager {
    private List<WeakReference<EventListener>> listeners = new ArrayList<>();

    public void addListener(EventListener listener) {
        listeners.add(new WeakReference<>(listener));
    }

    public void fireEvent() {
        for (WeakReference<EventListener> ref : listeners) {
            EventListener listener = ref.get();
            if (listener != null) {
                listener.onEvent();
            }
        }
    }

    public interface EventListener {
        void onEvent();
    }
}

应用场景

  • 避免监听器或回调导致的内存泄漏(如 Android 中的 Handler)。

  • WeakHashMap 实现临时键值存储(键被回收时条目自动删除)。

四、虚引用(PhantomReference)

1. 基本概念

虚引用是最弱的引用类型,无法通过虚引用访问对象。其唯一目的是在对象被回收时收到系统通知(通过 ReferenceQueue)。虚引用必须与引用队列(ReferenceQueue)配合使用。

2. 代码示例:资源清理
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class ResourceCleanupExample {
    private static class Resource {
        @Override
        protected void finalize() throws Throwable {
            System.out.println("Resource finalized");
        }
    }

    public static void main(String[] args) {
        ReferenceQueue<Resource> queue = new ReferenceQueue<>();
        PhantomReference<Resource> phantomRef = 
            new PhantomReference<>(new Resource(), queue);

        // 触发 GC
        System.gc();

        try {
            // 等待虚引用被加入队列(最多等待500ms)
            java.lang.ref.Reference<? extends Resource> ref = queue.remove(500);
            if (ref != null) {
                System.out.println("Resource被回收,执行清理操作");
                // 清理资源(如关闭文件句柄、释放Native内存)
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
Resource finalized
Resource被回收,执行清理操作

应用场景

  • 追踪对象被回收的时机,执行最终的资源清理(如释放堆外内存)。

  • 结合 ReferenceQueue 实现精细化的对象生命周期管理。


五、四种引用对比

引用类型回收时机用途访问对象
强引用永不回收(除非置为null)常规对象直接访问
软引用内存不足时回收缓存通过get()访问
弱引用下次GC时回收防止内存泄漏(如监听器)通过get()访问
虚引用对象被回收后收到通知资源清理无法访问

六、总结

  • 强引用:默认选择,用于长期存活的对象。

  • 软引用:适合内存敏感的缓存,避免OOM。

  • 弱引用:防止内存泄漏,如监听器、WeakHashMap

  • 虚引用:资源清理和对象回收跟踪。

合理利用不同引用类型,可以在内存管理和性能优化之间找到平衡。实际开发中,应根据业务场景选择最合适的引用类型,避免滥用导致不可预见的性能问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码里看花‌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值