对象的强引用,软引用,弱引用和虚引用的区别是什么?
2 个回答
我疯狂地奔跑,只想为你承担一切的伤害,我竖起了山丘,不愿你看见我丑陋的脸庞。凌霄在 Java 中,对象的引用类型分为四类:**强引用**(Strong Reference)、**软引用**(Soft Reference)、**弱引用**(Weak Reference)和**虚引用**(Phantom Reference)。这些引用类型的区别主要在于**对象的垃圾回收(GC)策略**,它们控制了在内存不足或 GC 过程中,**对象是否可以被回收**。 下面分别介绍每种引用类型的区别。 ### 1. **强引用(Strong Reference)** 这是 Java 中最常见、最常用的引用类型。**强引用**是指直接通过引用变量来引用对象,当某个对象被强引用时,**垃圾回收器不会回收该对象**,即使发生了内存不足,也不会回收强引用的对象,除非程序主动将该引用置为 `null` 或该对象不再可达。 #### 示例: ```java Object obj = new Object(); // 强引用 ``` - 当你创建了一个对象 `obj`,并将其引用赋值给变量 `obj` 时,这就是一个**强引用**。 - 只要强引用存在,**GC 不会回收这个对象**。 **特点**: - 强引用是默认的引用类型,最常用。 - 只要有强引用指向一个对象,垃圾回收器就不会回收该对象。 - 强引用可以导致**内存泄漏**,因为它强制对象在内存中一直存在,直到引用被显式置为 `null`。 ### 2. **软引用(Soft Reference)** **软引用**是一种相对较弱的引用类型。它允许我们保留对对象的引用,**但是当内存不足时,垃圾回收器会回收这些软引用指向的对象**,以防止内存溢出。也就是说,软引用的对象只有在 JVM 判断内存充足时才不会被回收;如果内存不足,这些对象就会被回收。 #### 示例: ```java SoftReference<Object> softRef = new SoftReference<>(new Object()); ``` - 通过 `SoftReference` 类创建软引用对象。`softRef` 引用指向的对象在内存充足时不会被回收,但当内存不足时,它会被 GC 回收。 **特点**: - 软引用通常用于实现**内存敏感的缓存**。当内存足够时,缓存对象会保留在内存中;当内存不足时,这些缓存对象可以被回收,避免内存溢出。 - 适合在缓存场景中使用,例如缓存图片等大对象,当系统内存不足时可以释放这些缓存对象来腾出空间。 ### 3. **弱引用(Weak Reference)** **弱引用**比软引用更弱。**当一个对象只有弱引用时**,不论内存是否充足,**一旦垃圾回收器运行,弱引用指向的对象都会被回收**。弱引用非常适合用在**非强依赖对象**的场景,例如**WeakHashMap** 中的键,当键没有其他强引用存在时,它们可以被 GC 自动回收。 #### 示例: ```java WeakReference<Object> weakRef = new WeakReference<>(new Object()); ``` - `WeakReference` 类用于创建弱引用对象。`weakRef` 引用的对象会在下一次 GC 时被回收,无论内存是否充足。 **特点**: - 弱引用在下一次 GC 时会被回收,无论当前系统内存是否充足。 - 常用于**WeakHashMap** 的键的引用,如果键不再被强引用持有,则 GC 会自动回收这些键值对。 ### 4. **虚引用(Phantom Reference)** **虚引用**(幽灵引用或幻象引用)是最弱的一种引用类型,**对象即使有虚引用也随时可能被 GC 回收**。与其他引用不同,虚引用仅仅是为了监控对象的生命周期,它**不能通过虚引用获取对象的实例**,虚引用必须和**引用队列(ReferenceQueue)** 一起使用,当对象被 GC 回收时,虚引用会被加入到引用队列中,程序可以通过检查队列来知道对象何时被回收。 #### 示例: ```java PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), new ReferenceQueue<>()); ``` - `PhantomReference` 需要与 `ReferenceQueue` 一起使用。当对象被回收后,虚引用会被加入到 `ReferenceQueue` 中,用于通知程序对象已被回收。 **特点**: - 虚引用主要用于**跟踪对象的销毁**,也就是说通过虚引用,可以知道对象何时被垃圾回收。 - 不能通过虚引用直接访问对象,通过虚引用 `get()` 方法返回的永远是 `null`。 - 常用于一些特殊的资源管理场景,比如确保在对象销毁时进行某些清理工作。 ### 5. **引用类型的对比总结** | 引用类型 | GC 回收条件 | 用途 | 特点 | |------------|------------------------------|------------------------------|---------------------------------| | **强引用** | 永远不会被回收 | 常规对象引用 | 最常见,默认的引用类型 | | **软引用** | 内存不足时回收 | 实现缓存 | 内存足够时保留,内存不足时回收 | | **弱引用** | GC 运行时回收,无论内存是否足够| WeakHashMap 的键 | 对象的生命周期较短,随时回收 | | **虚引用** | 被 GC 回收时放入引用队列 | 跟踪对象被回收的时间 | 无法获取对象实例,必须配合队列使用 | ### 6. **具体使用场景** 1. **强引用**: - 应用程序中的大多数引用都是强引用,适用于默认的场景,例如: ```java String str = new String("Hello"); // 强引用 ``` 2. **软引用**: - 适用于**缓存**场景。比如图片缓存、文件缓存等,软引用允许对象在内存足够时保留,但在内存不足时可以回收,减少内存溢出风险。 - 示例:使用 `SoftReference` 来缓存图片。 ```java SoftReference<Bitmap> imageCache = new SoftReference<>(bitmap); ``` 3. **弱引用**: - 适用于需要在对象不再被使用时自动回收的场景,比如 `WeakHashMap` 的键,当某个键不再有其他引用时,GC 可以自动回收它。 - 示例:使用 `WeakReference` 来管理不重要的对象。 ```java WeakReference<Object> weakRef = new WeakReference<>(new Object()); ``` 4. **虚引用**: - 适用于**跟踪对象回收的时间**或进行一些特殊资源的管理。例如可以通过虚引用配合 `ReferenceQueue` 在对象被回收时执行一些清理操作。 - 示例:通过 `PhantomReference` 跟踪对象回收事件。 ```java ReferenceQueue<Object> refQueue = new ReferenceQueue<>(); PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), refQueue); ``` ### 总结 - **强引用**:最常用的引用类型,只要有强引用,GC 就不会回收对象,可能会导致内存泄漏。 - **软引用**:适用于缓存,内存不足时可以回收软引用的对象。 - **弱引用**:比软引用更弱,GC 运行时会回收弱引用的对象,用于弱键映射等场景。 - **虚引用**:最弱的引用类型,用于监控对象的生命周期,不能获取对象实例,常用于资源管理。 不同的引用类型在不同场景下有各自的用途,选择合适的引用类型可以帮助我们在内存管理中做出更好的决策。发布于 2023-04-28 23:17 •IP属地 重庆举报评论收藏
纵然前路迷茫,纵然天隔一方,纵然我手中的刀刃已然破碎,也无法阻挡我寻找你的道路。小洋#### 强引用 就是普通的变量对对象的引用,强引用的对象不会被系统回收。 #### 软引用 当内存空间足够时,软引用的对象不会被系统回收。当内存空间不足时,软引用的对象可能被系统回收。通常用于内存敏感的程序中。 #### 弱引用 引用级别比软引用低,对于只有软引用的对象,不管内存是否足够,在垃圾回收时, 都可能会被系统回收。 #### 虚引用 虚引用主要用于跟踪对象被垃圾回收的状态,在垃圾回收时可以收到一个通知。发布于 2022-02-14 02:33 •IP属地 安徽举报评论收藏
公众号进入网站体验更佳

