问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

一文秒懂强引用,软引用、弱引用、虚引用!

创作时间:
作者:
@小白创作中心

一文秒懂强引用,软引用、弱引用、虚引用!

引用
CSDN
1.
https://blog.csdn.net/qq_56158663/article/details/146160391

目录

  • 一、 强引用 💪
  • 二、 软引用 ☁️
  • 三、 弱引用 🍃
  • 四、 虚引用 👻
  • 五、总结:

🌟本文将为您详细讲解Java中的四种引用类型:强引用、软引用、弱引用和虚引用。这些引用类型在Java内存管理中扮演着重要角色,理解它们的特性和使用场景对于编写高效、稳定的Java程序至关重要。让我们一起深入探讨这些引用类型的核心概念和实际应用吧!🤗

一、 强引用 💪

意义:
new
出来的对象,只要有变量指向它,它就死不了。 💀 GC 绝对不会回收它。

特点:

  • 最常见的引用类型。
  • 只要有强引用指向一个对象,该对象就不会被垃圾回收器回收。
  • 即使内存不足,JVM 宁愿抛出
    OutOfMemoryError
    (OOM) 💥 异常,也不会回收强引用指向的对象。

代码示例:

public class StrongReferenceExample {
    public static void main(String[] args) {
        // 创建一个对象,并用强引用指向它
        Object obj = new Object();
        Object strongRef = obj;
        // 此时,obj和strongRef都指向同一个对象
        System.out.println(obj);
        System.out.println(strongRef);
        // 将obj置为null,但strongRef仍然指向该对象
        obj = null;
        System.gc(); // 建议JVM进行垃圾回收,但不保证立即执行
        // 即使obj为null,strongRef指向的对象仍然存在,不会被回收
        System.out.println(strongRef); // 仍然能打印出对象
        // 只有当strongRef也置为null时,该对象才有可能被回收
        strongRef = null;
        System.gc();
    }
}

解释:

Object obj = new Object();
创建了一个新的
Object
对象,并用强引用
obj
指向它。

Object strongRef = obj;
又创建了一个强引用
strongRef
,也指向同一个对象。

  • 即使
    obj = null;

    strongRef
    仍然指向该对象,所以该对象不会被回收。
  • 只有当
    strongRef = null;
    ,并且 GC 执行时,该对象才有可能被回收。

二、 软引用 ☁️

意义:对象还有用,但也不是非要不可。 🤷 内存够用的时候,留着它;内存不够用的时候,就回收它。

特点:

  • 比强引用弱一些的引用类型。
  • 只有当 JVM 认为内存不足时,才会回收软引用指向的对象。
  • 通常用于实现缓存。 📦

代码示例:

import java.lang.ref.SoftReference;

public class SoftReferenceExample {
    public static void main(String[] args) {
        // 创建一个对象
        Object obj = new Object();
        // 创建一个软引用指向该对象
        SoftReference<Object> softRef = new SoftReference<>(obj);
        // 将obj置为null,断开强引用
        obj = null;
        // 从软引用中获取对象
        Object retrievedObj = softRef.get();
        System.out.println("Before GC: " + retrievedObj);
        // 尝试进行垃圾回收
        System.gc();
        // 再次从软引用中获取对象
        retrievedObj = softRef.get();
        System.out.println("After GC: " + retrievedObj);
        // 模拟内存不足的情况
        try {
            byte[] b = new byte[1024 * 1024 * 700]; // 700MB
        } catch (OutOfMemoryError e) {
            System.out.println("OOM occurred");
        }
        // 再次尝试获取对象
        retrievedObj = softRef.get();
        System.out.println("After OOM: " + retrievedObj);
    }
}

解释:

SoftReference softRef = new SoftReference<>(obj);
创建了一个软引用,指向
obj
对象。

obj = null;
断开了强引用,只剩下软引用。

softRef.get();
尝试从软引用中获取对象。

  • 第一次
    System.gc()
    后,由于内存充足,软引用指向的对象可能不会被回收,
    retrievedObj
    仍然不为
    null
  • byte[] b = new byte[1024 * 1024 * 700];
    尝试分配大量内存,模拟内存不足的情况。 如果 JVM 认为内存不足,会回收软引用指向的对象。
  • 在 OOM 之后,再次
    softRef.get()

    retrievedObj
    可能为
    null
    ,表示对象已经被回收。

三、 弱引用 🍃

意义:对象可有可无,下次 GC 来的时候,直接回收它。 👋

特点:

  • 比软引用更弱的引用类型。
  • 只要垃圾回收器运行,无论内存是否充足,都会回收弱引用指向的对象。
  • 通常用于实现
    WeakHashMap
    等数据结构。 🗺️

代码示例:

import java.lang.ref.WeakReference;

public class WeakReferenceExample {
    public static void main(String[] args) {
        // 创建一个对象
        Object obj = new Object();
        // 创建一个弱引用指向该对象
        WeakReference<Object> weakRef = new WeakReference<>(obj);
        // 将obj置为null,断开强引用
        obj = null;
        // 从弱引用中获取对象
        Object retrievedObj = weakRef.get();
        System.out.println("Before GC: " + retrievedObj);
        // 尝试进行垃圾回收
        System.gc();
        // 再次从弱引用中获取对象
        retrievedObj = weakRef.get();
        System.out.println("After GC: " + retrievedObj);
    }
}

解释:

WeakReference weakRef = new WeakReference<>(obj);
创建了一个弱引用,指向
obj
对象。

obj = null;
断开了强引用,只剩下弱引用。

System.gc();
执行垃圾回收。

  • 由于是弱引用,GC 会立即回收该对象。
  • weakRef.get()
    返回
    null
    ,表示对象已经被回收。

四、 虚引用 👻

意义:对象被回收之后,会收到一个通知。 🔔 虚引用根本拿不到对象,它的存在仅仅是为了让你知道对象被回收了。

特点:

  • 最弱的引用类型。
  • 虚引用不能单独使用,必须和引用队列(
    ReferenceQueue
    )一起使用。
  • 当垃圾回收器回收一个只有虚引用的对象时,会将这个虚引用放入与之关联的引用队列中。
  • 主要用于跟踪对象被垃圾回收的状态,进行一些清理工作。 🧹

代码示例:

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class PhantomReferenceExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个对象
        Object obj = new Object();
        // 创建一个引用队列
        ReferenceQueue<Object> queue = new ReferenceQueue<>();
        // 创建一个虚引用,并关联引用队列
        PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue);
        // 将obj置为null,断开强引用
        obj = null;
        // 尝试进行垃圾回收
        System.gc();
        // 暂停一段时间,等待垃圾回收器执行
        Thread.sleep(1000);
        // 检查引用队列
        if (queue.poll() != null) {
            System.out.println("Phantom Reference is enqueued.");
        } else {
            System.out.println("Phantom Reference is NOT enqueued.");
        }
    }
}

解释:

ReferenceQueue queue = new ReferenceQueue<>();
创建一个引用队列,用于存放被回收的虚引用。

PhantomReference phantomRef = new PhantomReference<>(obj, queue);
创建一个虚引用,指向
obj
对象,并关联引用队列。

obj = null;
断开了强引用,只剩下虚引用。

System.gc();
执行垃圾回收。


  • obj
    被回收时,
    phantomRef
    会被放入
    queue
    中。
  • queue.poll()
    从队列中取出虚引用,如果取到,说明对象已经被回收。

五、总结:

特性
强引用 (💪)
软引用 (☁️)
弱引用 (🍃)
虚引用 (👻)
强度
最强
较强
较弱
最弱
回收时机
永远不会被GC回收,除非没有引用指向
内存不足时,GC可能回收
GC运行时,立即回收
GC运行时,立即回收
用途
正常对象引用
缓存
WeakHashMap
跟踪对象回收状态,资源清理
获取对象
直接访问
get(),可能为null
get(),可能为null
无法直接获取对象
是否必须与ReferenceQueue一起使用
解释
“死不了”
“可有可无,内存不够就回收”
“下次GC来就回收”
“对象被回收后,收到通知”

希望这篇文章能让你理解Java中的强引用、软引用、弱引用、虚引用!! 😊

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号