十分钟理解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中的弱引用编程开发技术共3页.pdf.zip
java的超简洁的知识点总结
java程序设计,ppt教案,教你更轻松的学习java
面试中经常问道的常量池优化技术,Java中的常量值技术是为了方便快捷的创建某些对象而出现的,当需要一个对象时,就可以从池中取一个出来(如果没有则创建一个,创建一个比引用一个要耗时),则在需要重复创建相等...
反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这篇文章带大家十分钟快速理解Java中的反射,有需要的可以参考借鉴。
讲了 java 的数据类型 和大体的编译过程,以及一些编程序常识性的运算符
输入倒计时时间后,显示剩余时间,时间到后有提示音和提示画面(无bug)
什么是单点登录?单点登录全称Single Sign On(以下简称SSO),是指在多系统应用群 中登录一个系统,便可在其他所有系统中得到授权而无需再次登录
精彩十分钟
闲来没事在日志中瞟见了个OutOfMemoryError错误,不由得想到前一段时间看到一篇面经里问到Java中是否有内存泄露,这个很久以前是留意过的,大体记得内存溢出和内存泄露是不同的,至于各自都有哪些情况,那个…额...
java图解,十分钟学习JAVA.很好学习java资料
这是一个用java多线程实现的网络编程。每十分钟会执行一次
主要介绍了java知识点System类,根据一次面试总结的,可以十分钟速懂System类,感兴趣的小伙伴们可以参考一下
在java中我找了一下关于计算两个日期之间相差的天数方法有10多种实现方法,下面总结一下常用的几种计算两个日期之间相差的天数实例
人教部编版一年级上册 道德与法治课间十分钟第二课时教案.pdf
java 得到当前分辩率 windows分辩率
Python十分钟入门指导、适合新手学习。
通俗易理解介绍websocket原理、属性、事件、方法,十分钟学会 很简单哦
HDFS+MapReduce+Hive+HBase 十分钟快速入门 对Hadoop家族进行简单讲解,集群配置实例讲解,快速入门
十分钟J2EE轻松入门,全面理解J2EE,初学J2EE者必看,概念级入门材料。