Java 四种引用类型介绍和演示

目录

    • 一、前言
    • 二、Java 四种引用类型
      • 强引用(StrongReference)
      • 软引用(SoftReference)
      • 弱引用(WeakReference)
      • 虚引用(PhantomReference)
    • 三、总结

一、前言

Java有四种引用类型:强引用、软引用、弱引用、虚引用,Java中默认声明的就是强引用,我们用的最多的也是强引用,这里会对每种引用关系做说明和演示。

  • 提前准备一个User类演示时需要使用
public class User {private Long id;
}

二、Java 四种引用类型

强引用(StrongReference)

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

User user = new User(); // 创建一个User对象,使用强引用
System.gc(); // 手动触发GC
if(user == null){System.out.println("user对象已经被GC回收    " + user);
}else {System.out.println("user对象没有被GC回收    " + user);
}
user = null; // 手动置null 取消引用

只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null,这样一来,JVM就可以适时的回收对象。

软引用(SoftReference)

如果一个对象只具有软引用,在内存空间足够的时候,就算手动触发垃圾回收,也是不会回收它的;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。

要模拟出这个效果需要在启动参数中设置堆内存大小:

-Xmx1M -Xms1M
SoftReference<User> softRef = new SoftReference(new User()); // 软引用
System.gc(); // 手动触发GC
if(softRef.get() == null){System.out.println("user对象已经被GC回收    " + softRef.get());
}else {System.out.println("user对象没有被GC回收    " + softRef.get());
}
// 模拟内存溢出 这里创建1M的Byte数组
try {Byte[] bytes = new Byte[1024 * 1024 * 1024];
}catch (OutOfMemoryError e){e.printStackTrace();
}
if(softRef.get() == null){System.out.println("user对象已经被GC回收    " + softRef.get());
}else {System.out.println("user对象没有被GC回收    " + softRef.get());
}

软引用可以结合ReferenceQueue来使用,当由于系统内存不足,导致软引用的对象被回收了,JVM会把这个软引用SoftReference对象加入到与之相关联的ReferenceQueue中,SoftReference 对象除了具有保存软引用的特殊性之外,也具有Java对象的一般性。所以,当软可及对象被回收之后,虽然这个 SoftReference 对象的get()方法返回 null,但这个 SoftReference 对象已经不再具有存在的价值,需要一个适当的清除机制,避免大量 SoftReference 对象带来的内存泄漏,使用 ReferenceQueue 清除失去了软引用对象SoftReference。

ReferenceQueue referenceQueue = new ReferenceQueue(); // 引用队列
SoftReference<User> softRef = new SoftReference(new User(),referenceQueue); // 软引用
System.gc(); // 手动触发GC
if(softRef.get() == null){System.out.println("user对象已经被GC回收    " + softRef.get());
}else {System.out.println("user对象没有被GC回收    " + softRef.get());
}
// 模拟内存溢出 这里创建1M的Byte数组
try {Byte[] bytes = new Byte[1024 * 1024 * 1024];
}catch (OutOfMemoryError e){e.printStackTrace();
}
if(softRef.get() == null){System.out.println("user对象已经被GC回收    " + softRef.get());
}else {System.out.println("user对象没有被GC回收    " + softRef.get());
}
// 当软引用User对象被回收后 referenceQueue.poll() 能获取到软引用SoftReference对象
if(softRef == referenceQueue.poll()){softRef = null;
}

弱引用(WeakReference)

只有弱引用的对象,当JVM触发gc时,就会回收该对象。与软引用不同的是,不管是否内存不足,弱引用都会被回收。弱引用也可以结合ReferenceQueue来使用,当由于系统触发gc,导致弱引用的对象被回收了,JVM会把这个弱引用WeakReference对象加入到与之相关联的ReferenceQueue中,不过由于垃圾收集器线程的优先级很低,所以弱引用不一定会被很快回收。

WeakReference<User> weakRef = new WeakReference(new User()); // 弱引用
if(weakRef.get() == null){System.out.println("user对象已经被GC回收    " + weakRef.get());
}else {System.out.println("user对象没有被GC回收    " + weakRef.get());
}
System.gc(); // 手动触发GC
if(weakRef.get() == null){System.out.println("user对象已经被GC回收    " + weakRef.get());
}else {System.out.println("user对象没有被GC回收    " + weakRef.get());
}

虚引用(PhantomReference)

虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于,虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。由于Object.finalize()方法的不安全性、低效性,常常使用虚引用完成对象回收前的资源释放工作。

User user = new User(); //创建一个强引用对象
ReferenceQueue referenceQueue = new ReferenceQueue(); // 引用队列
PhantomReference<User> phantomReference = new PhantomReference<>(user, referenceQueue); // 使用虚引用指向这个内存空间 并且绑定引用队列
System.out.println(phantomReference.get()); // 虚引用是获取不到引用值的 get方法返回的null
user = null; // 释放这个内存空间,此时只剩phantomReference通过虚引用指向它
System.gc(); // 手动触发GC
// 被清除的队列中取出被回收的对象
while (true) {Reference<? extends User> poll = referenceQueue.poll();if (poll!=null) {System.out.println("虚引用对象被回收 处理其它逻辑");return;}
}

三、总结

Java的四种引用类型的级别由高到低依次为:强引用 > 软引用 > 弱引用 > 虚引用

级别回收时机用途
强引用不会回收所有的直接引用
软引用内存不足时回收联合ReferenceQueue构造有效期短/占内存大/生命周期长的对象的二级高速缓冲器(内存不足才清空)
弱引用垃圾回收时联合ReferenceQueue构造有效期短/占内存大/生命周期长的对象的一级高速缓冲器(系统发生gc则清空)
虚引用垃圾回收时联合ReferenceQueue来跟踪对象被垃圾回收器回收的活动

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LintCode 1095 Maximum Swap 数字处理好题

1095 Maximum Swap Algorithms Medium Description Given a non-negative integer. You could choose to swap two digits of it. Return the maximum valued number you could get. Only $39.9 for the “Twitter Comment System Project Practice” within a limited time…

会声会影2024编辑过程很卡怎么解决

会声会影是一款常用的视频剪辑软件&#xff0c;在使用过程中&#xff0c;可能会遇到视频卡顿的情况。造成这种情况的原因有很多&#xff0c;下面我就给大家讲解一下用会声会影做视频会卡的原因&#xff0c;会声会影剪辑时卡顿怎么设置的方法。 会声会影 2022 安装包:https://so…

思维模型 心理防御机制

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。用幻想保护自己。 1 心理防御机制的应用 1.1 以下是心理防御机制在人际关系中的应用 1 心理防御机制的正向使用 小明在一次重要的演讲中犯了一个错误&#xff0c;他感到非常尴尬和失落。…

vue+echarts实现桑吉图的效果

前言&#xff1a; 在我们项目使用图形的情况下&#xff0c;桑吉图算是冷门的图形了&#xff0c;但是它可以实现我们对多级数据之间数据流向更好的展示的需求&#xff0c;比如&#xff0c;我们实际数据流向中&#xff0c;具有1对多&#xff0c;多对多的情况下&#xff0c;如果用…

深入理解mysql的explain命令

1 基础 全网最全 | MySQL EXPLAIN 完全解读 1.1 MySQL中EXPLAIN命令提供的字段包括&#xff1a; id&#xff1a;查询的标识符。select_type&#xff1a;查询的类型&#xff08;如SIMPLE, PRIMARY, SUBQUERY等&#xff09;。table&#xff1a;查询的是哪个表。partitions&…

《Java 并发编程艺术》笔记(上)

如何减少上下文切换 减少上下文切换的方法有无锁并发编程、CAS算法、使用最少线程和使用协程。 无锁并发编程&#xff1a;多线程竞争锁时&#xff0c;会引起上下文切换&#xff0c;所以多线程处理数据时&#xff0c;可以用一些办法来避免使用锁。如将数据的 ID 按照 Hash 算法…

空对象指针为什么有时候能调用成员函数

在谈这个话题之前呢&#xff0c;还是得了解一下内存布局&#xff0c;以x86的32位系统为例&#xff1a; 然后得明确一点&#xff0c;NULL指针是无法访问的&#xff0c;如果强行访问&#xff0c;则会引发异常 然而空对象指针有时候却能够调用成员函数 class C { public:int a;st…

kali linux下可用的wine QQ/微信

kali linux下可以使用网页版本的 QQ/微信。但是体验差强人意&#xff0c;无法截图&#xff0c;无法发送word中的复制文字&#xff0c;反而能发送excel表格中的复制文字&#xff0c;无法拖拽发送等多种难以接受的体验。 所以尝试wine 版本&#xff0c;好处是通过交叉编译&#…

【华为OD题库-078】查字典-Java

题目 输入一个单词前缀和一个字典&#xff0c;输出包含该前缀的单词 输入描述: 单词前缀字典长度字典 字典是—个有序单词数组 输入输出都是小写 输出描述: 所有包含该前缀的单词&#xff0c;多个单词换行输出 若没有则返回-1 示例1 输入: b 3 a b c 输出: b 示例2 输入: abc 4…

multipartFile转file类型方法

1&#xff1a;在Java中&#xff0c;可以通过MultipartFile对象的transferTo()方法将文件保存到本地临时文件中&#xff0c;并使用该临时文件创建一个File对象&#xff0c;进而得到File类型的文件 import org.springframework.web.multipart.MultipartFile; import java.io.Fil…

【linux系统编程】编辑器gcc/g++

目录 Linux下的编辑器 介绍&#xff1a; 1&#xff0c;编辑器gcc/g 1-1&#xff0c;系统的编译过程 1-2&#xff0c;预处理过程 1-3&#xff0c;编译过程 1-4&#xff0c;汇编过程 1-5&#xff0c;链接过程 Linux下的编辑器 介绍&#xff1a; Linux系统下可支持很多高…

Python读写txt文件数据

&#x1f388; 博主&#xff1a;一只程序猿子 &#x1f388; 博客主页&#xff1a;一只程序猿子 博客主页 &#x1f388; 个人介绍&#xff1a;爱好(bushi)编程&#xff01; &#x1f388; 创作不易&#xff1a;如喜欢麻烦您点个&#x1f44d;或者点个⭐&#xff01; &#x1f…

html和css写淘宝的快速导航条

目录 1、css代码 2、html代码 1、css代码 <style>* {margin: 0;padding: 0;list-style: none;text-decoration: none;}.nav {width: 900px;height: 40px;background-color: rgb(247, 249, 250);margin: 50px auto;padding-left: 30px;}.nav>li {float: left;width: 1…

说说maven有什么优缺点?

Maven是一个流行的Java项目管理和构建工具&#xff0c;它可以帮助开发人员更有效地管理项目依赖关系、构建项目和部署代码。下面我将详细介绍Maven的优缺点&#xff1a; 优点&#xff1a; 一致性和标准化&#xff1a;Maven提供了一套标准的构建和项目管理工具&#xff0c;使得…

电力工程设计手册 全套31本

书号书名定价出版社名称9787519824358电力工程设计手册 01 火力发电厂总图运输设计200.00中国电力出版社9787519829780电力工程设计手册 02 火力发电厂热机通用部分设计210.00中国电力出版社9787519826994电力工程设计手册 03 火力发电厂锅炉及辅助系统设计290.00中国电力出版社…

云天励飞即将亮相“双数峰会”

第二届数字政府建设峰会暨数字湾区发展论坛即将在12月8-10日举办。本次“双数”峰会上&#xff0c;云天励飞将与CEC联合展示&#xff0c;重点展出大模型在数字政府领域的创新应用&#xff0c;以及云天励飞自主研发的大模型推理芯片。 “云天天书”包含通用大模型、行业大模型、…

昇腾npu上构建modelbox webUI开发容器教程

官方提供了modelbox webUI教程&#xff0c;但是&#xff0c;该教程有以下缺点&#xff1a; 在容器刚启动时&#xff0c;配置中的访问控制列表没有包含本地PC的IP&#xff0c;这导致如果想从本地PC访问远程服务器上容器的webUI&#xff0c;需要登入容器修改配置文件&#xff0c…

GO设计模式——2、工厂方法模式(创建型)

目录 工厂方法模式&#xff08;Factory Method Pattern&#xff09; 工厂模式的核心角色 优缺点 代码实现 工厂方法模式&#xff08;Factory Method Pattern&#xff09; 工厂方法模式&#xff08;Factory Method Pattern&#xff09;又叫作多态性工厂模式&#xff0c;指的…

Kali Linux 2023.4 已经发布了!

开发人员推出了 Kali Linux 2023.4&#xff0c;这是2023 年发行版的第四个也是最后一个版本。 新产品已经可供下载&#xff0c;包含15 个新工具和 GNOME 45。 Offective Security 团队报告称&#xff0c;在今年的最终版本中&#xff0c;操作系统中并没有添加太多新功能&…

什么是海牙公约?

一、什么是海牙公约&#xff1f; "海牙公约" 通常是指1899年和1907年两次在海牙举行的国际和平会议所达成的一系列国际公约。这两次会议的目标是通过国际合作来促进和平、防止战争&#xff0c;并制定一些规则和原则&#xff0c;以限制武装冲突的影响。以下是其中两个…