【JVM】面试题-Java中有哪些引用类型


Java中有哪些引用类型

1、强引用

Java中默认声明的就是强引用,比如:

复制代码
Object obj = new Object();
obj = null;

只要强引用存在,垃圾回收器将永远不会回收被引用的对象。

如果想被回收,可以将对象置为null

复制代码
======= 🌟 青柠来相伴,代码更简单。🌟 =======
📚 本文所有内容,我都整理在了 青柠合集 里。👇
🎯 搜索关注【青柠代码录】,即可查看所有合集文章 ~
======= 🌟 =================== 🌟 =======

最传统的"引用"的定义,是指在程序代码之中普遍存在的引用赋值,即类似"0bject obj=new object()"这种引用关系。

无论任何情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象。

复制代码
public class StrongRefDemo {
    public static void main(String[] args) {
        // 默认就是强引用
        Object obj = new Object();

        // 只要强引用还在,GC 绝不回收
        System.gc();
        System.out.println("GC后对象还在:" + obj);

        // 断开强引用,对象无引用指向,可被GC回收
        obj = null;

        System.gc();
        System.out.println("置null后:" + obj); // null
    }
}

2、软引用(SoftReference)

在内存足够的时候,软引用不会被回收,只有在内存不足时,系统才会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会跑出内存溢出异常。

复制代码
byte[] buff = new byte[1024 * 1024];
SoftReference<byte[]> sr = new SoftReference<>(buff);

在系统将要发生内存溢出之前,将会把这些对象列入回收范围之中进行第二次回收。如果这次回收后还没有足够的内存,才会抛出内存溢出异常。

复制代码
import java.lang.ref.SoftReference;

public class SoftRefDemo {
    public static void main(String[] args) {
        // 创建大对象
        byte[] data = new byte[1024 * 1024 * 10];
        
        // 包装为软引用
        SoftReference<byte[]> softRef = new SoftReference<>(data);

        // 断开强引用
        data = null;

        // 内存充足时,能拿到对象
        System.out.println("内存充足,获取对象:" + softRef.get());

        // 若内存爆满触发GC,软引用对象会被回收,get() 返回 null
    }
}

3、弱引用(WeakReference)

进行垃圾回收时,弱引用就会被回收。

被弱引用关联的对象,只能生存到下一次垃圾收集之前。当垃圾收集器工作时,无论内存空间是否足够,都会回收掉被弱引用关联的对象。

复制代码
import java.lang.ref.WeakReference;

public class WeakRefDemo {
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        // 包装弱引用
        WeakReference<Object> weakRef = new WeakReference<>(obj);

        // 断开强引用
        obj = null;

        // 触发GC
        System.gc();
        Thread.sleep(200);

        // GC之后,弱引用对象直接被回收,get() = null
        System.out.println("GC后弱引用获取:" + weakRef.get()); // null
    }
}

4、虚引用(PhantomReference)

一个对象是否有虛引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用,来获得一个对象的实例。为一个对象设置虛引用关联的,唯一目的,就是能在这个对象被收集器回收时,收到一个系统通知(回收跟踪)。

无法通过虚引用获得对象,用 PhantomReference 实现虚引用,虚引用的用途是在 gc 时,返回一个通知。

复制代码
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class PhantomRefDemo {
    public static void main(String[] args) throws InterruptedException {
        ReferenceQueue<Object> queue = new ReferenceQueue<>();
        Object obj = new Object();

        // 虚引用必须配合引用队列才有意义
        PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue);

        // 断开强引用
        obj = null;

        System.gc();
        Thread.sleep(200);

        // 虚引用永远拿不到对象,get() 一定是 null
        System.out.println("虚引用get:" + phantomRef.get()); // null

        // 回收后虚引用会进入队列,用来做善后清理
        System.out.println("队列是否收到通知:" + queue.poll());
    }
}

5、引用队列(ReferenceQueue)

引用队列可以与软引用、弱引用、虚引用一起配合使用。

当垃圾回收器准备回收一个对象时,如果发现它还有引用,就会在回收对象之前,把这个引用加入到引用队列中。

程序可以通过判断引用队列中,是否加入了引用,来判断被引用的对象,是否将要被垃圾回收,这样可以在对象被回收之前,采取一些必要的措施。

示例:弱引用 + 引用队列

复制代码
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;

public class RefQueueDemo {
    public static void main(String[] args) throws InterruptedException {
        // 1. 创建引用队列
        ReferenceQueue<Object> queue = new ReferenceQueue<>();

        // 2. 普通对象 + 弱引用绑定队列
        Object obj = new Object();
        WeakReference<Object> weakRef = new WeakReference<>(obj, queue);

        // 3. 断开强引用
        obj = null;

        // GC 回收时,引用都会自动进队列
        System.gc();
        Thread.sleep(200);

        // 4. 从队列取出引用,说明对象即将被回收
        WeakReference<?> pollRef = (WeakReference<?>) queue.poll();
        if (pollRef != null) {
            System.out.println("收到回收通知,对象准备被GC回收,可做资源清理");
        }
    }
}

补充:软引用 / 虚引用 ,绑定队列套路完全一样

相关推荐
摇滚侠4 分钟前
《SpringBoot 3:入门与应用实战》第 15 章 生产级特性 监控指标 Metrics 阅读笔记
java·spring boot·笔记
Ming_studying6 分钟前
Python + SQLite FTS5 构建本地文档全文搜索器:增量索引、中文检索与高亮
jvm·数据库·python·sqlite
弹简特30 分钟前
【Java项目-企悦抽】11-用户与认证模块-实现用户登录03(结束登录功能)-完成测试+对接前端+登录拦截器
java·开发语言
大模型丫丫1 小时前
Loop Engineering:从强化学习视角看 Agent 循环的本质
java·人工智能·学习
数电发票API1 小时前
税局接口,需要的来~~
java
骇客野人1 小时前
IntelliJ IDEA 使用技巧
java·ide·intellij-idea
Jul1en_2 小时前
【Java 脚手架】封装通用工具类-1
java·spring boot·分布式·spring·spring cloud
我命由我123452 小时前
Java 开发 - List subList 方法
java·windows·操作系统·list·intellij-idea·idea·intellij idea
关于不上作者榜就原神启动那件事2 小时前
从 MDC 到 Agent:我手搓的文档路由协议,在 Spring AI Alibaba 里找到了正式实现
java·人工智能·spring·ai·agent
亦暖筑序3 小时前
重新认识 AgentScope-Java 2.0:ReActAgent 负责推理,HarnessAgent 负责运行
java·后端·agent