一文带你了解Java四大引用类型

60 阅读4分钟

前言

Java中的四大引用是Java面试中的热门考点,今天我们结合生活中的小栗子来重温一下这块知识。

我说白了,我白说了😂。Java中的引用类型就像是我们和对象之间的"关系强度",决定了垃圾回收器(GC)什么时候能带走这个对象。我用现实生活中的关系来比喻这四种引用,配合代码例子带大家彻底理解。

在这里插入图片描述

强引用(结婚证关系)

强引用是Java程序中最常见的引用类型,也是默认的引用方式。

特点:只要结婚证在,夫妻关系就永远存在

// 强引用就像结婚
public class StrongReferenceDemo {
    public static void main(String[] args) {
        // 领结婚证(创建强引用)
        Object 老公 = new Object(); 
        
        // 想离婚必须主动去民政局
        laogong= null; 
        
        // 现在GC才能来回收这个"laogong"对象
        System.gc();
    }
}

现实生活中

  • 你和你对象领了结婚证(强引用)
  • 只要不离婚(不置null),法律上你们永远是夫妻
  • 民政局(GC)没有权利单方面解除你们的婚姻关系

软引用(恋爱关系)

软引用用来描述一些还有用但非必需的对象。

特点:平时甜甜蜜蜜,遇到现实压力(内存不足)可能分手

// 软引用就像谈恋爱
public class SoftReferenceDemo {
    public static void main(String[] args) {
        // 开始谈恋爱
        SoftReference<Object> girlfriend= new SoftReference<>(new Object());
        
        System.out.println("热恋期:" + girlfriend.get()); // 能约到女朋友
        
        try {
            // 生活压力背上房贷(内存不足)
            Object[] fangdai= new Object[Integer.MAX_VALUE];
        } catch (OutOfMemoryError e) {
            System.out.println("压力太大后:" + girlfriend.get()); // null,女朋友跑了
        }
    }
}

现实生活中

  • 谈恋爱没有法律约束(软引用)
  • 平时相处和正常关系没区别
  • 一旦你经济困难(内存不足),对方可能离开

使用场景

  • 缓存朋友圈照片(内存够就留着,不够就删)
  • 浏览器网页缓存

弱引用(朋友关系)

弱引用比软引用更弱一些,只能生存到下一次垃圾回收发生之前。

特点:说散就散,GC一来立刻结束

// 弱引用就像酒肉朋友
public class WeakReferenceDemo {
    public static void main(String[] args) {
        // 交了个朋友
        WeakReference<Object> jiurouFriend= new WeakReference<>(new Object());
        
        System.out.println("聚餐时:" + jiurouFriend.get()); // 还能约出来
        
        System.gc(); // 破产了
        
        System.out.println("破产后:" + jiurouFriend.get()); // null,朋友消失了
    }
}

现实生活中

  • 酒肉朋友(弱引用)只能同享福
  • 你一出事(GC),他们就马上消失了
  • 比谈恋爱(软引用)更脆弱

虚引用(阴阳两界关系)

虚引用是最弱的一种引用关系,也被大家称为"幽灵引用"。

特点:对象已经"死了",但想知道葬礼什么时候举行

// 虚引用就像阴阳眼
public class PhantomReferenceDemo {
    public static void main(String[] args) {
        // 阴间使者观察名单(引用队列)
        ReferenceQueue<Object> yinjian= new ReferenceQueue<>();
        // 给活人贴上符咒
        Object zhangsan = new Object();
        PhantomReference<Object> fuzhou= new PhantomReference<>(zhangsan , yinjian);
        System.out.println("活人能看见吗?" + fuzhou.get()); // 永远null
        zhangsan = null; // 张三寄了
        System.gc();
        // 检查阴间使者有没有来收人
        Reference<?> guihun = yinjian.poll();
        if(guihun != null) {
            System.out.println("张三的葬礼可以安排了");
        }
    }
}

特殊机制

  • 就像阴阳眼,你看不见鬼(get()返回null)
  • 但能知道谁死了(通过队列收到通知)
  • 适合在对象死后执行清理工作

引用队列(ReferenceQueue)

引用队列可以与软引用、弱引用和虚引用一起使用,用于在对象被回收后收到通知。

工作原理 :

创建引用时关联一个ReferenceQueue

当引用对象被垃圾回收后,引用本身会被加入队列

程序可以通过轮询队列来获知对象被回收的事件

ReferenceQueue<Object> queue = new ReferenceQueue<>();
WeakReference<Object> weakRef = new WeakReference<>(new Object(), queue);

// 监控队列
new Thread(() -> {
    try {
        Reference<?> ref = queue.remove();
        System.out.println("对象已被回收");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();

四种引用对比表

引用类型现实比喻GC时的表现能否get()获取典型应用
强引用领结婚证死也不分开普通对象创建
软引用谈恋爱困难时就分手缓存
弱引用酒肉朋友说散就散WeakHashMap/临时缓存
虚引用阴阳眼观亡魂死后才通知不能资源回收监控

这样是不是好记多了?每种引用都有适合的场景,就像人际关系也要分亲疏远近~

本篇文章到这里就结束了,欢迎大家点赞收藏关注,感谢各位小伙伴们的支持!

在这里插入图片描述