十分钟理解Java中的弱引用
1. What——什么是弱引用?
Java中的弱引用具体指的是java.lang.ref.WeakReference<T>类,我们首先来看一下官方文档对它做的说明:
弱引用对象的存在不会阻止它所指向的对象变被垃圾回收器回收。弱引用最常见的用途是实现规范映射(canonicalizing mappings,比如哈希表)。
假设垃圾收集器在某个时间点决定一个对象是弱可达的(weakly reachable)(也就是说当前指向它的全都是弱引用),这时垃圾收集器会清除所有指向该对象的弱引用,然后垃圾收集器会把这个弱可达对象标记为可终结(finalizable)的,这样它们随后就会被回收。与此同时或稍后,垃圾收集器会把那些刚清除的弱引用放入创建弱引用对象时所登记到的引用队列(Reference Queue)中。
实际上,Java中存在四种引用,它们由强到弱依次是:强引用、软引用、弱引用、虚引用。下面我们简单介绍下除弱引用外的其他三种引用:
-
强引用(Strong Reference):通常我们通过new来创建一个新对象时返回的引用就是一个强引用,若一个对象通过一系列强引用可到达,它就是强可达的(strongly reachable),那么它就不被回收
-
软引用(Soft Reference):软引用和弱引用的区别在于,若一个对象是弱引用可达,无论当前内存是否充足它都会被回收,而软引用可达的对象在内存不充足时才会被回收,因此软引用要比弱引用“强”一些
-
虚引用(Phantom Reference):虚引用是Java中最弱的引用,那么它弱到什么程度呢?它是如此脆弱以至于我们通过虚引用甚至无法获取到被引用的对象,虚引用存在的唯一作用就是当它指向的对象被回收后,虚引用本身会被加入到引用队列中,用作记录它指向的对象已被销毁。
2. Why——为什么使用弱引用?
考虑下面的场景:现在有一个Product类代表一种产品,这个类被设计为不可扩展的,而此时我们想要为每个产品增加一个编号。一种解决方案是使用HashMap<Product, Integer>。于是问题来了,如果我们已经不再需要一个Product对象存在于内存中(比如已经卖出了这件产品),假设指向它的引用为productA,我们这时会给productA赋值为null,然而这时productA过去指向的Product对象并不会被回收,因为它显然还被HashMap引用着。所以这种情况下,我们想要真正的回收一个Product对象,仅仅把它的强引用赋值为null是不够的,还要把相应的条目从HashMap中移除。显然“从HashMap中移除不再需要的条目”这个工作我们不想自己完成,我们希望告诉垃圾收集器:“在只有HashMap中的key在引用着Product对象的情况下,就可以回收相应Product对象了。” 显然,根据前面弱引用的定义,使用弱引用能帮助我们达成这个目的。我们只需要用指向Product对象的弱引用对象来作为HashMap中的键就可以了。
3. How——如何使用弱引用?
拿上面介绍的场景举例,我们使用一个指向Product对象的弱引用对象来作为HashMap的键,只需这样定义这个弱引用对象:
productA = new Product(...); WeakReference<Product> weakProductA = new WeakReference<>(productA);
现在,若引用对象weakProductA就指向了Product对象productA。那么我们怎么通过weakProduct获取它所指向的Product对象productA呢?很简单,只需要下面这句代码:
Product product = weakProductA.get();
实际上,对于这种情况,Java类库为我们提供了WeakHashMap类,使用和这个类,它的键自然就是弱引用对象,无需我们再手动包装原始对象。这样一来,当productA变为null时(表明它所引用的Product已经无需存在于内存中),这时指向这个Product对象的就是由弱引用对象weakProductA了,那么显然这时候相应的Product对象时弱可达的,所以指向它的弱引用会被清除,这个Product对象随即会被回收,指向它的弱引用对象会进入引用队列中。
下面我们来简单地介绍下引用队列的概念。实际上,WeakReference类有两个构造函数:
WeakReference(T referent) //创建一个指向给定对象的弱引用
WeakReference(T referent, ReferenceQueue<? super T> q) //创建一个指向给定对象并且登记到给定引用队列的弱引用
我们可以看到第二个构造方法中提供了一个ReferenceQueue类型的参数,通过提供这个参数,我们便把创建的弱引用对象注册到了一个引用队列上,这样当它被垃圾回收器清除时,就会把它送入这个引用队列中,我们便可以对这些被清除的弱引用对象进行统一管理。
相关推荐
Java中的弱引用编程开发技术是Java内存管理的一个重要概念,对于优化内存使用和防止内存泄漏具有关键作用。本文将深入探讨这一主题,帮助你在这十分钟内建立起对弱引用的理解。 首先,我们需要知道Java的内存区域...
### 十分钟JAVA从入门到放弃 —— 超简洁的知识点总结 #### 面向对象的三大特征 **封装**:封装是面向对象编程的一个核心概念,它指的是将数据(属性)和操作这些数据的方法(行为)捆绑在一起,形成一个整体——...
本章会介绍Java中的数组,包括一维数组和多维数组的使用。同时,集合框架(如ArrayList、LinkedList、HashSet、HashMap等)的概念和操作也将被讲解,这是处理和存储多个对象的关键工具。 第5章:异常处理 Java中的...
首先,我们需要理解Java中如何处理时间。Java提供了一个名为`java.time`的包,其中包含许多类用于处理日期和时间,如`LocalDateTime`, `Instant`, 和 `Duration`等。在这个倒计时器中,我们可能使用`Duration`类来...
讲了 java 的数据类型 和大体的编译过程,以及一些编程序常识性的运算符
首先,Java中的多线程允许程序同时执行多个任务,提高资源利用率,提升程序性能。在Java中,创建线程主要有两种方式:继承`Thread`类和实现`Runnable`接口。在继承`Thread`类的情况下,你需要重写`run()`方法,而在...
1. **JDBC**:Java Database Connectivity,Java数据库连接,是Java中用来访问数据库的标准API,允许Java程序与各种类型的数据库进行交互。 2. **JNDI**:Java Naming and Directory Interface,Java命名和目录接口...
4. **字符串处理**: String类在Java中广泛使用,了解其不可变性、常用方法(如concat、substring、indexOf等)以及StringBuilder或StringBuffer类用于字符串拼接。 5. **异常处理**: Java提供了一套完善的异常处理...
在传统的单系统登录中,会话ID存储在cookie中,该cookie的域决定了它能被哪些子域所共享。如果多系统使用了相同的域名(如*.***),则可以通过统一cookie的域来实现跨子系统的会话共享。然而,这种方法的局限性在于...
2. XPath的基本概念和在Java中应用XPath进行数据提取的方法。 3. 数据采集和解析的基本流程,以及可能遇到的问题和解决方案。 4. 如何处理网络请求和解析响应,理解HTTP协议的基本原理。 5. 对源码阅读和理解的能力...
闲来没事在日志中瞟见了个OutOfMemoryError错误,不由得想到前一段时间看到一篇面经里问到Java中是否有内存泄露,这个很久以前是留意过的,大体记得内存溢出和内存泄露是不同的,至于各自都有哪些情况,那个…额...
【精彩十分钟】是一种创新的教育理念,旨在充分利用中小学课间的十分钟时间,发挥学生的主体作用,增强他们的动手能力,提升身体健康素质,并通过丰富的课间活动来促进学生的全面发展。这一理念指出,教师不仅要关注...
- 难点在于让学生理解并实践在活动中遵守秩序和规则,积极参与有益且文明的课间活动。 4. **教学方法**: - 教师采用情景烘托、引导质疑、重点引领和榜样示范的教学策略。 - 学生通过自主学习、合作讨论和游戏...
Java中的`System`类是Java标准库中的一个核心类,位于`java.lang`包下,它提供了一系列与系统相关的操作。这个类是`final`修饰的,不能被继承,其包含的功能广泛,涉及标准输入输出、环境变量访问、类库加载、数组...
标题中的“全国预警信息获取每十分钟更新一次.zip”指出这是一个关于获取全国预警信息的系统,其特点是每十分钟更新一次数据。这个系统可能是一个实时监控和处理预警信息的应用,旨在为用户提供及时、准确的气象预警...
教学资源以PPT的形式呈现,旨在帮助学生理解和欣赏一首描绘下课十分钟快乐时光的歌曲。 首先,教案中包含了歌曲的歌词,通过歌词我们可以看出,这首歌描绘了孩子们在下课铃声响起后的喜悦心情,他们利用这宝贵的...
本篇文章将深入讲解如何在十分钟内通过ZK进行快速入门,以及在"gettingStarted-master"压缩包中的代码示例。 首先,让我们了解ZK的核心概念。ZK的核心在于它的组件模型,它提供了许多预先构建的UI组件,如按钮、...
这个“易语言源码十分钟邮件模块源码.rar”压缩包显然是一个与电子邮件发送相关的编程资源,它包含了易语言编写的模块,可以帮助开发者快速构建能够发送邮件的功能。 首先,我们来看看主要的文件: 1. **十分钟邮件...