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

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

相关推荐
张不才1 小时前
CPU 100% 了怎么办?Java 性能排障的标准化操作
java·后端
shepherd1113 小时前
吞吐量提升 10 倍:高并发大批量数据处理任务的架构演进与性能调优
java·后端·架构
plainGeekDev5 小时前
单例模式 → object 声明
android·java·kotlin
用户298698530146 小时前
Java 实现 Word 文档文本与图片提取的方法
java·后端
SimonKing7 小时前
铁子,IntelliJ IDEA 2026.1.3来了,升不升?
java·后端·程序员
咖啡八杯18 小时前
GoF设计模式——策略模式
java·后端·spring·设计模式
用户128526116021 天前
我把祖传Java项目重构后,接口响应从3s砍到了200ms,只改了这几行代码
java
Linsk1 天前
组件 = 模板 + 业务逻辑
java·前端·vue.js
星沉远浦1 天前
用Gemini高效解决Java代码报错难以定位的问题
java