10分钟带你理解Java中的弱引用

 更新时间:2016年08月30日 11:31:12   投稿:daisy  
这篇文章将带大家快速理解Java中弱引用,文章介绍的很详细,对大家学习Java很有帮助哦,有需要的可以参考借鉴。

前言

本文尝试从What、Why、How这三个角度来探索Java中的弱引用,帮助大家理解Java中弱引用的定义、基本使用场景和使用方法。

一、 What——什么是弱引用?

Java中的弱引用具体指的是java.lang.ref.WeakReference<T>类,我们首先来看一下官方文档对它做的说明:

     弱引用对象的存在不会阻止它所指向的对象被垃圾回收器回收。弱引用最常见的用途是实现规范映射(canonicalizing mappings,比如哈希表)。

     假设垃圾收集器在某个时间点决定一个对象是弱可达的(weakly reachable)(也就是说当前指向它的全都是弱引用),这时垃圾收集器会清除所有指向该对象的弱引用,然后把这个弱可达对象标记为可终结(finalizable)的,这样它随后就会被回收。与此同时或稍后,垃圾收集器会把那些刚清除的弱引用放入创建弱引用对象时所指定的引用队列(Reference Queue)中。

实际上,Java中存在四种引用,它们由强到弱依次是:强引用软引用弱引用虚引用

下面我们简单介绍下除弱引用外的其他三种引用:

1、强引用(Strong Reference):通常我们通过new来创建一个新对象时返回的引用就是一个强引用,若一个对象通过一系列强引用可到达,它就是强可达的(strongly reachable),那么它就不被回收

2、软引用(Soft Reference):软引用和弱引用的区别在于,若一个对象是弱引用可达,无论当前内存是否充足它都会被回收,而软引用可达的对象在内存不充足时才会被回收,因此软引用要比弱引用“强”一些

3、虚引用(Phantom Reference):虚引用是Java中最弱的引用,那么它弱到什么程度呢?它是如此脆弱以至于我们通过虚引用甚至无法获取到被引用的对象,虚引用存在的唯一作用就是当它指向的对象被回收后,虚引用本身会被加入到引用队列中,用作记录它指向的对象已被回收。

二、Why——为什么使用弱引用?

考虑下面的场景:现在有一个Product类代表一种产品,这个类被设计为不可扩展的,而此时我们想要为每个产品增加一个编号。一种解决方案是使用HashMap<Product, Integer> 。于是问题来了,如果我们已经不再需要一个Product对象存在于内存中(比如已经卖出了这件产品),假设指向它的引用为productA,我们这时会给productA赋值为null,然而这时productA过去指向的Product对象并不会被回收,因为它显然还被HashMap引用着。所以这种情况下,我们想要真正的回收一个Product对象,仅仅把它的强引用赋值为null是不够的,还要把相应的条目从HashMap中移除。显然“从HashMap中移除不再需要的条目”这个工作我们不想自己完成,我们希望告诉垃圾收集器:在只有HashMap中的key在引用着Product对象的情况下,就可以回收相应Product对象了。显然,根据前面弱引用的定义,使用弱引用能帮助我们达成这个目的。我们只需要用一个指向Product对象的弱引用对象来作为HashMap中的key就可以了。

三、How——如何使用弱引用?

拿上面介绍的场景举例,我们使用一个指向Product对象的弱引用对象来作为HashMapkey,只需这样定义这个弱引用对象:

Product 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秒杀之redis限流操作详解

    java秒杀之redis限流操作详解

    这篇文章主要为大家详细介绍了java秒杀之redis限流操作,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • Java数据结构之LinkedList的用法详解

    Java数据结构之LinkedList的用法详解

    链表(Linked list)是一种常见的基础数据结构,是一种线性表。Java的LinkedList(链表) 类似于 ArrayList,是一种常用的数据容器,本文就来简单讲讲它的使用吧
    2023-05-05
  • Java实战之实现在线小说阅读系统

    Java实战之实现在线小说阅读系统

    本文主要介绍了一个通过Java实现的在线电子书小说阅读系统,文中用到的技术有Layui、Springboot、SpringMVC、HTML、FTP、JavaScript、JQuery等,感兴趣的可以试试
    2022-01-01
  • Java实现word/pdf转html并在线预览

    Java实现word/pdf转html并在线预览

    这篇文章主要为大家详细介绍了如何利用Java语言实现word、pdf文件转html并在线预览的功能,文中的示例代码讲解详细,需要的可以参考一下
    2023-05-05
  • 让你五分钟彻底理解Spring MVC

    让你五分钟彻底理解Spring MVC

    其实MVC就是处理Web请求的一种框架模式,如果你对MVC不太熟悉的话可以看下本文,这篇文章主要给大家介绍了关于如何让你五分钟彻底理解Spring MVC的相关资料,需要的朋友可以参考下
    2021-10-10
  • Java使用modbus-master-tcp实现modbus tcp通讯

    Java使用modbus-master-tcp实现modbus tcp通讯

    这篇文章主要为大家详细介绍了另外一种Java语言的modbux tcp通讯方案,那就是modbus-master-tcp,文中的示例代码讲解详细,需要的可以了解下
    2023-12-12
  • Java内部类和异常类的概念以及使用

    Java内部类和异常类的概念以及使用

    这篇文章主要介绍了Java内部类和异常类的概念以及使用,文中有非常详细的代码以及注释,适合正在学习java基础的同学们使用,需要的朋友可以参考下
    2021-04-04
  • 用java实现的获取优酷等视频缩略图的实现代码

    用java实现的获取优酷等视频缩略图的实现代码

    想获取优酷等视频缩略图,在网上没有找到满意的资料,参考了huangdijia的PHP版工具一些思路,写了下面的JAVA版代码。。其实也可以做成JS版的
    2013-05-05
  • 利用Maven入手Spring Boot第一个程序详解

    利用Maven入手Spring Boot第一个程序详解

    这篇文章主要给大家介绍了关于如何利用Maven入手Spring Boot第一个程序的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-02-02
  • struts2获取服务器临时目录的方法

    struts2获取服务器临时目录的方法

    这篇文章主要为大家详细介绍了struts2获取服务器临时目录的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-09-09

最新评论