Java、Android引用类型

Java/Android中有四种引用类型,分别是:
Strong reference - 强引用
Soft Reference - 软引用
Weak Reference - 弱引用
Phantom Reference - 虚引用

不同的引用类型有着不同的特性,同时也对应着不同的使用场景。

Strong reference - 强引用

实际编码中最常见的一种引用类型。常见形式如:A a = new A();等。强引用本身存储在栈内存中,其存储指向对内存中对象的地址。一般情况下,当对内存中的对象不再有任何强引用指向它时,垃圾回收机器开始考虑可能要对此内存进行的垃圾回收。如当进行编码:a = null,此时,刚刚在堆中分配地址并新建的a对象没有其他的任何引用,当系统进行垃圾回收时,堆内存将被垃圾回收。

SoftReference、WeakReference、PhantomReference都是类java.lang.ref.Reference的子类。Reference作为抽象基类,定义了其子类对象的基本操作。Reference子类都具有如下特点:

  • Reference子类不能无参化直接创建,必须至少以强引用对象为构造参数,创建各自的子类对象;
  • 因为1中以强引用对象为构造参数创建对象,因此,使得原本强引用所指向的堆内存中的对象将不再只与强引用本身直接关联,与Reference的子类对象的引用也有一定联系。且此种联系将可能影响到对象的垃圾回收。

根据不同的子类对象对其指示对象(强引用所指向的堆内存中的对象)的垃圾回收不同的影响特点,分别形成了三个子类,即SoftReference、WeakReference和PhantomReference

Soft Reference - 软引用

软引用的一般使用形式如下:
A a = new A();
SoftReference srA = new SoftReference(a);
通过对象的强引用为参数,创建了一个SoftReference对象,并使栈内存中的wrA指向此对象。
此时,进行如下编码:a = null,对于原本a所指向的A对象的垃圾回收有什么影响呢?
先直接看一下下面一段程序的输出结果:

public class ReferenceTest {public static void main(String[] args) {A a = new A();SoftReference<A> srA = new SoftReference<A>(a);a = null;if (srA.get() == null) {System.out.println("a对象进入垃圾回收流程");} else {System.out.println("a对象尚未被回收" + srA.get());}// 垃圾回收System.gc();if (srA.get() == null) {System.out.println("a对象进入垃圾回收流程");} else {System.out.println("a对象尚未被回收" + srA.get());}}
}class A {}
输出结果为:
a对象尚未被回收A@4807ccf6
a对象尚未被回收A@4807ccf6

当 a = null后,堆内存中的A对象将不再有任何的强引用指向它,但此时尚存在srA引用的对象指向A对象。当第一次调用srA.get()方法返回此指示对象时,由于垃圾回收器很有可能尚未进行垃圾回收,此时get()是有结果的,这个很好理解。当程序执行System.gc();强制垃圾回收后,通过srA.get(),发现依然可以得到所指示的A对象,说明A对象并未被垃圾回收。那么,软引用所指示的对象什么时候才开始被垃圾回收呢?需要满足如下两个条件:
1.当其指示的对象没有任何强引用对象指向它;
2.当虚拟机内存不足时。
因此,SoftReference变相的延长了其指示对象占据堆内存的时间,直到虚拟机内存不足时垃圾回收器才回收此堆内存空间。

Weak Reference - 弱引用

同样的,软引用的一般使用形式如下:
A a = new A();
WeakReference wrA = new WeakReference(a);
当没有任何强引用指向此对象时, 其垃圾回收又具有什么特性呢?

public class ReferenceTest {public static void main(String[] args) {A a = new A();WeakReference<A> wrA = new WeakReference<A>(a);a = null;if (wrA.get() == null) {System.out.println("a对象进入垃圾回收流程");} else {System.out.println("a对象尚未被回收" + wrA.get());}// 垃圾回收System.gc();if (wrA.get() == null) {System.out.println("a对象进入垃圾回收流程");} else {System.out.println("a对象尚未被回收" + wrA.get());}}
}class A {}
输出结果为:
a对象尚未被回收A@52e5376a
a对象进入垃圾回收流程

输出的第一条结果解释同上。当进行垃圾回收后,wrA.get()将返回null,表明其指示对象进入到了垃圾回收过程中。因此,对弱引用特点总结为:
WeakReference不改变原有强引用对象的垃圾回收时机,一旦其指示对象没有任何强引用对象时,此对象即进入正常的垃圾回收流程。
那么,依据此特点,很可能有疑问:WeakReference存在又有什么意义呢?
其主要使用场景见于:当前已有强引用指向强引用对象,此时由于业务需要,需要增加对此对象的引用,同时又不希望改变此引用的垃圾回收时机,此时WeakReference正好符合需求,常见于一些与生命周期的场景中。

ReferenceQueue

对于SoftReference和WeakReference,还有一个构造器参数为ReferenceQueue,当SoftReference或WeakReference所指示的对象确实被垃圾回收后,其引用将被放置于ReferenceQueue中。注意上文中,当SoftReference或WeakReference的get()方法返回null时,仅是表明其指示的对象已经进入垃圾回收流程,此时对象不一定已经被垃圾回收。而只有确认被垃圾回收后,其引用才会被放置于ReferenceQueue中。

public static void main(String[] args) {A a = new A();ReferenceQueue referenceQueue = new ReferenceQueue();WeakReference<Object> weakReference = new WeakReference<Object>(a, referenceQueue);a = null;if(weakReference.get() == null){System.out.println("a对象进入垃圾回收流程");}else {System.out.println("a对象尚未被回收" + weakReference.get());}System.out.println("rq item:" + referenceQueue.poll());System.gc();if(weakReference.get() == null){System.out.println("a对象进入垃圾回收流程");}else {System.out.println("a对象尚未被回收" + weakReference.get());}System.out.println("rq item:" + referenceQueue.poll());}public static class A{@Overrideprotected void finalize() throws Throwable {System.out.println("A finalize");super.finalize();}}
输出结果为:
a对象尚未被回收@4554617c
rq item:null
a对象进入垃圾回收流程
rq item:null
A finalize

当调用System.gc()后,输出‘a对象进入垃圾回收流程’说明a已经开始进入了垃圾回收流程,但是还未被真正回收,因为Java对象被回收时会调用期finalize方法;此时我们立刻调用referenceQueue.poll()得到的是空,这样验证了对象只有gc已回收后WeakReference或SoftReference才会被加入ReferenceQueue。

现在我们再gc后,进行一段时间的延时后再调用referenceQueue.poll():
 public static void main(String[] args) {A a = new A();ReferenceQueue referenceQueue = new ReferenceQueue();WeakReference<Object> weakReference = new WeakReference<Object>(a, referenceQueue);a = null;if(weakReference.get() == null){System.out.println("a对象进入垃圾回收流程");}else {System.out.println("a对象尚未被回收" + weakReference.get());}System.out.println("rq item:" + referenceQueue.poll());System.gc();if(weakReference.get() == null){System.out.println("a对象进入垃圾回收流程");}else {System.out.println("a对象尚未被回收" + weakReference.get());}try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("rq item:" + referenceQueue.poll());}public static class A{@Overrideprotected void finalize() throws Throwable {System.out.println("A finalize");super.finalize();}}
输出结果
a对象尚未被回收@4554617c
rq item:null
a对象进入垃圾回收流程
A finalize
rq item:@74a14482

此时referenceQueue中存在了WeakReference,实验的结果也就不言而喻了。

PhantomReference虚引用

与SoftReference或WeakReference相比,PhantomReference主要差别体现在如下几点:

  • PhantomReference只有一个构造函数PhantomReference(T referent, ReferenceQueue<? super T> q),因此,PhantomReference使用必须结合ReferenceQueue;
  • 不管有无强引用指向PhantomReference的指示对象,PhantomReference的get()方法返回结果都是null。
public class ReferenceTest {public static void main(String[] args) {A a = new A();ReferenceQueue<A> rq = new ReferenceQueue<A>();PhantomReference<A> prA = new PhantomReference<A>(a, rq);System.out.println("prA.get():" + prA.get());a = null;System.gc();try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("rq item:" + rq.poll());}
}class A {}
输出结果为:
prA.get():null
rq item:java.lang.ref.PhantomReference@1da12fc0

代码中的Thread.sleep(1);作用与上例中相同,都是确保垃圾回收线程能够执行。否则,进进入垃圾回收流程而没有真正被垃圾回收的指示对象的虚引用是不会被加入到PhantomReference中的。

与WeakReference相同,PhantomReference并不会改变其指示对象的垃圾回收时机。ReferenceQueue的作用主要是用于监听Java对象是否已经被垃圾回收。

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

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

相关文章

网络安全,文明上网(2)加强网络安全意识

前言 在当今这个数据驱动的时代&#xff0c;对网络安全保持高度警觉已经成为每个人的基本要求。 网络安全意识&#xff1a;信息时代的必备防御 网络已经成为我们生活中不可或缺的一部分&#xff0c;信息技术的快速进步使得我们对网络的依赖性日益增强。然而&#xff0c;网络安全…

实时数据研发 | Flink技术栈

下周要开始接触一些实时的内容了&#xff0c;想来是很幸运的&#xff0c;这是我在新人培训上提问过技术前辈的问题&#xff1a;“想学习实时相关技术&#xff0c;但是部门没有类似的需求&#xff0c;应该如何提升&#xff1f;”当时师姐说先用心去学&#xff0c;然后向主管证明…

Spark SQL 之 QueryStage

ExchangeQueryStageExec ExchangeQueryStageExec 分为两种

探索 RocketMQ:企业级消息中间件的选择与应用

一、关于RocketMQ RocketMQ 是一个高性能、高可靠、可扩展的分布式消息中间件&#xff0c;它是由阿里巴巴开发并贡献给 Apache 软件基金会的一个开源项目。RocketMQ 主要用于处理大规模、高吞吐量、低延迟的消息传递&#xff0c;它是一个轻量级的、功能强大的消息队列系统&…

设计模式之 责任链模式

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;旨在将多个处理对象通过链式结构连接起来&#xff0c;形成一条处理请求的链条。每个处理对象都有机会处理请求&#xff0c;或者将请求传递给链中的下一个对象。这样&#x…

Flink-Source的使用

Data Sources 是什么呢&#xff1f;就字面意思其实就可以知道&#xff1a;数据来源。 Flink 做为一款流式计算框架&#xff0c;它可用来做批处理&#xff0c;也可以用来做流处理&#xff0c;这个 Data Sources 就是数据的来源地。 flink在批/流处理中常见的source主要有两大类…

python开发之Linux

文章目录 1. 基础2. 进阶链接压缩/解压缩 文件权限用户远程操作编辑文件软件安装 1. 基础 # 查看当前目录下文件 ls# 查看当前目录 pwd# 清除界面内容 clear# 切换目录 cd# 创建目录 mkdir# 创建文件 touch 文件 vi 文件# 强制删除 rm -rf # 复制文件 cp 复制文件 复制文件路径…

【数据结构】七种常用排序总结

一、七种排序及其讲解 以下为七种排序的讲解&#xff1a; 【数据结构】插入排序——直接插入排序 和 希尔排序 【数据结构】选择排序——选择排序 和 堆排序 【数据结构】交换排序——冒泡排序 和 快速排序 【数据结构】归并排序 —— 递归及非递归解决归并排序 二、排序的…

计算机网络(14)ip地址超详解

先看图&#xff1a; 注意看第三列蓝色标注的点不会改变&#xff0c;A类地址第一个比特只会是0&#xff0c;B类是10&#xff0c;C类是110&#xff0c;D类是1110&#xff0c;E类是1111. IPv4地址根据其用途和网络规模的不同&#xff0c;分为五个主要类别&#xff08;A、B、C、D、…

HashMap底层原理

jdk1.8之后hashmap底层结构 jdk1.8之后&#xff0c;是哈希表数据结构&#xff0c;也可以说是数组链表或红黑树&#xff0c;下图是没有添加数据的一个hashmap。 现在开始添加数据&#xff0c;看下面具体步骤 put操作 如下&#xff0c;我们来简单看看hashmap的put源码&#xff…

【GD32】(三) ISP基本使用

0 前言 有一块GD32的板子不知道为啥用着用着就下载不了程序了&#xff0c;没办法&#xff0c;只能另寻他法。作为STM32的平替&#xff0c;GD32的功能和STM32基本是一致的&#xff0c;所以也可以使用ISP来下载程序。于是就开始复活这块板子。 1 BOOT模式 对于熟悉STM32开发的人…

摄像机视频分析软件下载LiteAIServer视频智能分析平台玩手机打电话检测算法技术的实现

随着科技的不断进步&#xff0c;摄像机视频分析软件的发展已经为我们的生活带来了许多便捷。其中&#xff0c;LiteAIServer视频智能分析平台的玩手机打电话检测算法技术尤为突出&#xff0c;它利用先进的图像处理和人工智能技术&#xff0c;能够自动识别并监控视频中的玩手机或…

推荐几个 VSCode 流程图工具

Visual Studio Code&#xff08;简称VSCode&#xff09;是一个由微软开发的免费、开源的代码编辑器。 VSCode 发布于 2015 年&#xff0c;而且很快就成为开发者社区中广受欢迎的开发工具。 VSCode 可用于 Windows、macOS 和 Linux 等操作系统。 VSCode 拥有一个庞大的扩展市…

学习Prompt Turning

传统的微调因为代价很高&#xff0c;而且一旦权重很大&#xff0c;这种fine 微微的意思是调不动模型的&#xff0c;所以需要这种提示词调 mindnlp直接有 peft config peft_config PromptTuningConfig(task_type“SEQ_CLS”, num_virtual_tokens10) 方便我们进行prompt tunin…

2024 APMCM亚太数学建模C题 - 宠物行业及相关产业的发展分析和策略(详细解题思路)

在当下&#xff0c; 日益发展的时代&#xff0c;宠物的数量应该均为稳步上升&#xff0c;在美国出现了下降的趋势&#xff0c; 中国 2019-2020 年也下降&#xff0c;这部分变化可能与疫情相关。需要对该部分进行必要的解释说明。 问题 1: 基于附件 1 中的数据及您的团队收集的额…

若依-一个请求中返回多个表的信息

背景 主表是点位表关联子表 需要知道对应 合作商的信息关联子表 需要直到对应 区域的信息关联子表 需要直到对应 设备数量 实现的方案 关联实体相关的标签

AWTK-WEB 快速入门(1) - C 语言应用程序

先安装 AWTK Designer 用 AWTK Designer 新建一个应用程序 2.1. 新建应用程序 这里假设应用程序的名称为 AwtkApplicationC&#xff0c;后面会用到&#xff0c;如果使用其它名称&#xff0c;后面要做相应修改。 在窗口上放置一个按钮将按钮的名称改为 “close”将按钮的文本改…

客户流失分析综述

引言 客户流失这个术语通常用来描述在特定时间或合同期内停止与公司进行业务往来的客户倾向性[1]。传统上&#xff0c;关于客户流失的研究始于客户关系管理&#xff08;CRM&#xff09;[2]。在运营服务时&#xff0c;防止客户流失至关重要。过去&#xff0c;客户获取相对于流失…

PDF内容提取,MinerU使用

准备环境 # python 3.10 python3 -m pip install huggingface_hub python3 -m pip install modelscope python3 -m pip install -U magic-pdf[full] --extra-index-url https://wheels.myhloli.com下载需要的模型 import json import osimport requests from huggingface_hub…

Kafka 分区分配及再平衡策略深度解析与消费者事务和数据积压的简单介绍

Kafka&#xff1a;分布式消息系统的核心原理与安装部署-CSDN博客 自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例-CSDN博客 Kafka 生产者全面解析&#xff1a;从基础原理到高级实践-CSDN博客 Kafka 生产者优化与数据处理经验-CSDN博客 Kafka 工作流程解析&#xff1a…