深入解析 Java 的四大引用类型:强引用、软引用、弱引用、虚引用

文章目录

      • 1. 强引用(Strong Reference)
        • 特性
        • 使用场景
      • 2. 软引用(Soft Reference)
        • 声明方式
        • 特性
        • 使用场景
      • 3. 弱引用(Weak Reference)
        • 声明方式
        • 特性
        • 使用场景
      • 4. 虚引用(Phantom Reference)
        • 声明方式
        • 特性
        • 使用场景
      • 四种引用的对比总结
      • 如何选择使用?
      • 总结
      • 推荐阅读文章

在 Java 内存管理中, 引用的概念扮演着非常重要的角色。引用的强弱程度,直接影响对象在内存中的生存周期。Java 语言中定义了四种不同的引用类型: 强引用软引用弱引用虚引用,每一种引用类型都有独特的特性和适用场景。理解它们的区别和作用,不仅有助于提升 Java 内存管理的水平,也有助于开发更高效、稳定的应用程序。

今天我们就来聊聊这四种引用类型,看看它们各自的作用和使用场景。


1. 强引用(Strong Reference)

强引用是 Java 中最常见的引用类型,几乎所有普通对象创建出来的引用都是强引用。例如:

Object obj = new Object(); // 强引用
特性
  • 内存优先级最高:只要一个对象存在强引用关系,GC(垃圾回收器)绝不会回收它。
  • 容易造成内存泄漏:如果某些不再使用的对象还存在强引用,会导致内存一直无法释放,造成内存泄漏。
使用场景

强引用适合用于那些必须保留的对象,比如系统的核心对象、关键数据等。注意,使用强引用时要确保适时释放引用,以避免内存泄漏。


2. 软引用(Soft Reference)

软引用在内存紧张时会被回收。它是一种比较“灵活”的引用类型,通常用来实现缓存。

声明方式

可以通过 SoftReference 类来创建软引用:

SoftReference<Object> softRef = new SoftReference<>(new Object());
特性
  • 内存不紧张时不回收:只有在 JVM 内存不足时,垃圾回收器才会回收软引用对象。
  • 缓存实现利器:软引用特别适合用于缓存。内存充足时保留缓存对象,内存紧张时释放缓存,以确保内存资源可以被更重要的任务使用。
使用场景

适用于缓存场景。例如,在图片加载、文件缓存等场景下,利用软引用可以缓存对象,以便重复利用。如果内存不够用,缓存会自动被回收释放,减轻内存压力。


3. 弱引用(Weak Reference)

弱引用比软引用更弱,只要 GC 一发现弱引用对象,不管内存是否充足,都会立即回收它

声明方式

可以通过 WeakReference 类来创建弱引用:

WeakReference<Object> weakRef = new WeakReference<>(new Object());
特性
  • 易回收:弱引用对象几乎总是会被及时回收,这使得它很适合存放不重要的对象。
  • 避免内存泄漏:弱引用可以有效防止内存泄漏,适合用来管理临时对象或需要动态清除的数据。
使用场景

弱引用常用于存储像 ThreadLocal 中的键值对、某些映射中的临时对象(例如 WeakHashMap)等场景,确保它们在不被使用时能及时被垃圾回收。


4. 虚引用(Phantom Reference)

虚引用几乎是最弱的一种引用,它的特点是不影响对象的垃圾回收,也就是说,一个对象是否有虚引用都不会影响它的生命周期。虚引用更多的是为对象回收提供一种跟踪机制。

声明方式

可以通过 PhantomReference 类来创建虚引用:

PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), new ReferenceQueue<>());

注意:虚引用必须与 ReferenceQueue 一起使用,用来追踪对象何时被回收。

特性
  • 无法访问引用对象:通过虚引用无法访问对象的任何属性或方法。
  • 用作回收监控:在对象即将被 GC 回收时,虚引用会被加入 ReferenceQueue,可以通过 ReferenceQueue 来执行一些资源释放操作。
使用场景

虚引用通常用于管理直接内存文件资源的释放,尤其是那些不在 JVM 管理的内存资源。虚引用可以作为一种监控手段,确保对象被回收时,能自动清理掉相关资源。


四种引用的对比总结

引用类型GC 回收时机特性与使用场景
强引用从不回收常见引用类型,不适当清理会导致内存泄漏
软引用内存不足时回收适合缓存,内存紧张时自动回收
弱引用只要 GC 发现就回收适合存放临时性数据,防止内存泄漏
虚引用对象被回收时,在 ReferenceQueue 中可追踪仅用于资源释放的跟踪,不影响对象生命周期

如何选择使用?

  • 强引用:适用于必须持有、经常使用的对象,特别是核心数据。
  • 软引用:适合缓存数据,保证系统在内存充足时保留,内存不足时释放。
  • 弱引用:适合临时性数据或易回收对象,比如缓存中不重要的部分,数据不在意时效。
  • 虚引用:用于监控对象回收情况,适合管理非 Java 管理的资源。

总结

Java 的四大引用类型为我们提供了多样化的内存管理手段,使得我们能够灵活地控制对象的生命周期。通过合理利用这四种引用,不仅可以有效防止内存泄漏,还可以优化应用性能。理解这些引用的特性,结合不同应用场景,选择适合的引用类型,才能写出更高效的 Java 程序。

推荐阅读文章

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)
  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系
  • HTTP、HTTPS、Cookie 和 Session 之间的关系
  • 什么是 Cookie?简单介绍与使用方法
  • 什么是 Session?如何应用?
  • 使用 Spring 框架构建 MVC 应用程序:初学者教程
  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误
  • 如何理解应用 Java 多线程与并发编程?
  • 把握Java泛型的艺术:协变、逆变与不可变性一网打尽
  • Java Spring 中常用的 @PostConstruct 注解使用总结
  • 如何理解线程安全这个概念?
  • 理解 Java 桥接方法
  • Spring 整合嵌入式 Tomcat 容器
  • Tomcat 如何加载 SpringMVC 组件
  • “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”
  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”
  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)
  • 解密 Redis:如何通过 IO 多路复用征服高并发挑战!
  • 线程 vs 虚拟线程:深入理解及区别
  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!
  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”
  • Java 中消除 If-else 技巧总结
  • 线程池的核心参数配置(仅供参考)
  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)
  • Java 枚举的几个常用技巧,你可以试着用用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/12264.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

DAY59||并查集理论基础 |寻找存在的路径

并查集理论基础 并查集主要有两个功能&#xff1a; 将两个元素添加到一个集合中。判断两个元素在不在同一个集合 代码模板 int n 1005; // n根据题目中节点数量而定&#xff0c;一般比节点数量大一点就好 vector<int> father vector<int> (n, 0); // C里的一…

基于Spring Boot的乡政府管理系统设计与实现,LW+源码+讲解

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装乡政府管理系统软件来发挥其高效地信息处理的作用&#xf…

【NLP】使用 PyTorch 从头构建自己的大型语言模型 (LLM)

读完这篇文章后&#xff0c;你会取得什么成就&#xff1f;你将能够自己构建和训练大型语言模型 (LLM)&#xff0c;同时与我一起编写代码。虽然我们正在构建一个将任何给定文本从英语翻译成马来语的 LLM&#xff0c;但你可以轻松地修改此 LLM 架构以用于其他语言翻译任务。 LLM…

QT打包应用程序文件步骤

QT应用程序&#xff08;.exe&#xff09;打包复制到其他电脑 在QT程序在自己电脑编译好了后&#xff0c;需要打包给其他人。这里介绍一下详细步骤&#xff1a; 确定编译器 搜了很多相关的打包教程&#xff0c;但是还是会出现“应用程序无法正常启动(0xc000007b)”这类错误。经过…

JMeter进阶篇

目录 上篇导航&#xff1a; 总目录&#xff1a; 一、逻辑控制器&#xff1a; 1.逻辑控制器和关联&#xff1a; 2.if逻辑控制器&#xff1a; 3.forEach控制器&#xff1a; 4.循环控制器&#xff1a; 二、关联&#xff1a; 1.xpath&#xff1a; 2.正则表达式提取器&…

homework 2024.11.10 math 1 - math 6

小学1年级和小学6年级数学图形结合&#xff0c;以及习惯养成&#xff0c;过程改进 6年级数学&#xff1a; 一年级数学&#xff1a;

【Linux 31】网络层协议 - IP

文章目录 &#x1f308; 一、IP 协议的基本概念⭐ 1. TCP IP 能保证数据的可靠传输⭐ 2. 如何理解 IP地址⭐ 3. 路由选择⭐ 4. 主机 & 路由器 & 节点 &#x1f308; 二、IP 协议的报头格式⭐ 1. IP 协议的报头格式⭐ 2. 如何将 IP 报头和有效载荷分离⭐ 3. 如何将有效…

Mac中安装OhMyZsh

Mac中安装OhMyZsh 文章目录 Mac中安装OhMyZsh一、Homebrew二、OhMyZsh1、Oh-My-Zsh配置1.1&#xff1a;主题配置1.2&#xff1a;插件配置&#xff08;语法高亮和自动提示&#xff09;1、zsh-autosuggestions&#xff08;需下载安装&#xff09;&#xff1a;高亮显示所有支持的命…

7、computed计算属性使用

代码 Student.vue <template> <div><h2>computed计算属性使用</h2><input type"text" v-model"name"/><br/><input type"text" v-model"sex"/><br/>完整信息&#xff1a;{{info}}&…

SystemVerilog学习笔记(三):结构体与联合体

结构体 结构包含具有不同大小的不同数据类型&#xff0c;这些数据类型分组在一个结构体名称下。默认情况下&#xff0c;结构体最初是未压缩的形式&#xff0c;但可以使用“packed”关键字将其转换为压缩结构。 结构与普通数组不同&#xff0c;因为数组仅使用相同类型和大小的…

无人飞手培训机构大量新增,如何选择好的培训机构?

随着无人机技术的普及和应用领域的拓展&#xff0c;无人机飞手培训机构确实在大量新增。为了选择一家好的培训机构&#xff0c;可以从以下几个方面进行考量&#xff1a; 一、培训资质 官方认证&#xff1a;选择具备中国航空器拥有者及驾驶员协会&#xff08;AOPA-China&#x…

Wi-Fi背后的工作原理与技术发展历程介绍【无线通信小百科】

1个视频说清楚WIFI&#xff1a;频段/历程/技术参数/常用模块 智能手机拥有率越来越高的今天&#xff0c;大家已经习惯了通过无线网络上网的方式。除了在外面需要用手机流量&#xff0c;我们通常在家里或者机场&#xff0c;商场都可以通过Wi-Fi连接上网。本期文章将为大家介绍Wi…

入门车载以太网(4) -- 传输层(TCP\UDP)

目录 1.ECU通信方式的变化 2.传输层概述 2.1 UDP 2.2 TCP 3. TCP和ISO 15765-2 1.ECU通信方式的变化 我们先回顾下两种通信方式&#xff1a;Signal-Based Messaging、Service-Based Messaging。 Signal-Based Messaging 基于信号的通信方式&#xff0c;例如CAN通信&…

软件测试第二篇软件测试技术

第五章单元测试和集成测试的技术 单元静态测试主要由开发人员完成。 标准&#xff1a;规定什么能做&#xff0c;什么不能做。 规范&#xff1a;建议你要怎么做。 5.1.2 代码评审 代码评审是一种发现代码缺陷的另一种测试方法。 代码审查的最佳实践&#xff1a; 创建代码审…

w035基于web的学科竞赛管理

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0…

导航系统非完整性约束汽车运动公约

Back to FDISYSTEMS Knowledge Base 惯性&导航传感器 导航系统&运动约束 数学基础 & 约定 参考坐标系载体 & 传感器坐标系方向/旋转表示非线性卡尔曼滤波器SPKF汽车运动公约船舶运动公约 惯性传感器安装 惯性传感器运行 技术洞察 Knowledge Base /数学基础…

Centos8 安装 JDK / Python / MySQL / Redis / Nginx

安装 JDK 华为镜像 JDK 下载地址&#xff1a;https://repo.huaweicloud.com:8443/artifactory/java-local/jdk/ 这里安装 JDK8 为例&#xff1a; # 这里直接通过 wget 下载 wget https://repo.huaweicloud.com:8443/artifactory/java-local/jdk/8u202-b08/jdk-8u202-linux-x…

【Qt-ROS开发】使用 Qt Creator 构建和编译含 ROS 库的 Qt 项目

【Qt-ROS】使用 Qt Creator 构建和编译含 ROS 库的项目 网上大多数办法是在 Qt creator中安装 ros_qtc_plugin 插件&#xff0c;项目以 ROS1 工作空间的形式构建&#xff0c;还是使用 catkin 来构建整个项目。但是这种方式局限很大&#xff0c;导入 Qt 的组件反而变得很麻烦&a…

【RabbitMQ】07-业务幂等处理

1. 方式一 序列化设置唯一Id。 Beanpublic MessageConverter messageConverter() {Jackson2JsonMessageConverter jjmc new Jackson2JsonMessageConverter();jjmc.setCreateMessageIds(true);return jjmc;}RabbitListener(bindings QueueBinding(value Queue(name "d…

SparseDrive 论文学习

论文链接&#xff1a;https://arxiv.org/pdf/2405.19620 代码链接&#xff1a;https://github.com/swc-17/SparseDrive 解决了什么问题&#xff1f; 传统模块化的自动驾驶系统可以被解耦为不同的独立模块&#xff0c;如感知、预测和规划&#xff0c;这种范式会面临信息丢失和…