【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回收,可做资源清理");
        }
    }
}

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

相关推荐
秋饼9 小时前
JDK 27 企业级 AI 服务落地实战:G1 默认、紧凑对象头、后量子 TLS 与 JFR 脱敏全解析
java·ai·技术分享·后端开发
卓怡学长10 小时前
w176基于SpringBoot的医院管理系统
java·spring boot·spring·maven·intellij-idea
lemon_sjdk10 小时前
ObjectProperty
java·开发语言·算法
hh95010 小时前
Agent Plan x DeepSeek Harness:Agent 供应链安全与第三方插件审计
java·开发语言·安全·agent plan·adg成都社区·adg社区
吴声子夜歌10 小时前
Java面试——HBase原理及应用
java·面试·hbase
浪兎兎10 小时前
【Java Web】Servlet + JSP 笔记
java·前端·servlet
吴声子夜歌10 小时前
Java面试——ElasticSearch原理及应用
java·面试·es
lhldsg10 小时前
家政派单系统开发实战:从需求分析到智能调度全流程指南
java·junit·小程序·uni-app·需求分析
吴声子夜歌10 小时前
Java面试——Spring原理及应用(一)
java·spring·面试
灰阳阳10 小时前
Docker-数据卷命令解析
java·docker·eureka