先说结论:

首先,Java中有四种引用类型:强引用、软引用、弱引用、虚引用。-- 在 Java 1.2 中添加的,见 package java.lang.ref;

其次,这几个概念是与垃圾回收有关的。

然后,如果你不知道这几个概念,那你用的肯定都是强引用。例如 String str = new String(); 这个 strnew String() 的引用类型就是强引用。

那么弱引用是什么?

弱引用,就是引用与对象之间的联系很弱,弱到垃圾回收器会无视这个引用,直接回收对象。

软引用与弱引用类似,但只在内存不足时才会被回收。

虚引用最差,甚至不能通过 get() 获取到对象。

为什么需要弱引用?

先看一段代码:

 package cn.larry.weakref.pojo;

 public final class Product {
private String name; public Product() {
super();
} public Product(String name) {
super();
this.name = name;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "Product [name=" + name + "]";
} }
 package cn.larry.weakref.test;

 import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap; import org.junit.Test; import cn.larry.weakref.pojo.Product; public class WrTest {
private Product product = new Product("iPhone"); @Test
public void strongRef() {
Map<Product, Integer> map = new HashMap<>();
map.put(product, 111); product = null;// 关键
map.keySet().forEach(System.out::println);// 对象仍然存在!
}
}

在上面的代码中,虽然在第21行已经将 product引用置空(null),但是第22行的代码仍然可以访问到该引用最初指向的对象!

这时,如果map中有多个Key,Product类又不可修改(不能添加识别字段),那你怎么确定并删除这个Key,能否自动移除该Key?弱引用就可以满足这样的要求。

一个经典的场景就是缓存,特别是缓存图片(加载到内存中),此时缓存肯定会包含一个指向内存中图片缓存的引用。问题在于,如果使用强引用,你必须决定何时不再需要该缓存并手动移除它。

怎么使用弱引用?

代码如下(与上面的测试代码在同一个 WrTest 类中):

     @Test
public void weakRef_1() { ReferenceQueue<Product> rq = new ReferenceQueue<>();
// WeakReference<Product> wr=new WeakReference<Product>(product);
WeakReference<Product> wr = new WeakReference<Product>(product, rq);// 引用队列
System.out.println("wr是否已被添加至引用队列:" + wr.isEnqueued()); Map<WeakReference<Product>, Integer> map = new HashMap<>();
map.put(wr, 111); product = null;// 关键
// System.gc();// 关键 map.keySet().forEach(e -> System.out.println(e.get()));// 不gc()的话,还能访问对象,否则null。
System.out.println("wr是否已被添加至引用队列:" + wr.isEnqueued());
}

上面第4行构造了一个引用队列。

第5或6行构造了一个弱引用,区别在于是否指定引用队列。

如果指定了弱引用的引用队列,垃圾回收器会在回收对象之后将该弱引用添加至引用队列中 -- 可以在回收之后通过弱引用的 isEnqueued() 方法来判断。

需要注意:①必须将原强引用置空(第12行),且不能有其他强引用指向该对象;②必须主动调用垃圾回收器(第13行)。然后就能看到弱引用指向的对象已经不存在了(第15行) -- 弱引用本身还存在,所以map不为空。

但是,这时已经可以手动删除这个Key了。

更便捷的方法:

JDK提供了 WeakHashMap 可以更加方便的完成上面的工作,代码如下:

     @Test
public void weakRef_2() {
WeakHashMap<Product, Integer> map = new WeakHashMap<>();
map.put(product, 111); product = null;// 关键
// System.gc();//关键 map.keySet().forEach(System.out::println);// 不gc()的话,还能访问对象,否则null。 }

这种情况下,map.size()是0,即该Key自动被移除!!!

补充说明:

1、虽然可以主动调用垃圾回收器,但垃圾回收器并不总是会执行的。

2、Product类参考了 理解Java中的弱引用(Weak Reference) 中的pojo类。

参考

理解Java中的弱引用(Weak Reference)
译文:理解Java中的弱引用
 

Java的四种引用类型之弱引用的更多相关文章

  1. java中四种引用类型(对象的强、软、弱和虚引用)

    对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2 ...

  2. java中四种引用类型

    java中四种引用类型  今天看代码,里面有一个类java.lang.ref.SoftReference把小弟弄神了,试想一下,接触java已经有3年了哇,连lang包下面的类都不了解,怎么混.后来在 ...

  3. 你知道Java的四种引用类型吗

    关于java四种引用类型,我也是刚了解,特此记下! 在Java中提供了四个级别的引用:强引用,软引用,弱引用和虚引用.在这四个引用类型中,只有强引用FinalReference类是包内可见,其他三种引 ...

  4. java的四种引用类型

    java的引用分为四个等级:4种级别由高到低依次为:强引用.软引用.弱引用和虚引用. ⑴强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回 ...

  5. java中四种引用类型(转)

    今天看代码,里面有一个类java.lang.ref.SoftReference把小弟弄神了,试想一下,接触java已经有3年了哇,连lang包下面的类都不了解,怎么混.后来在网上查资料,感觉收获颇多, ...

  6. Java中的四种引用类型,强引用,软引用,弱引用,虚引用

    对于Java中的垃圾回收机制来说,对象是否被回收的标准在于该对象是否被引用.因此,引用也是JVM进行内存管理的一个重要概念. Java中对象的引用一般有以下4种类型: 1强引用  2软引用  3弱引用 ...

  7. Java中四种引用:强、软、弱、虚引用

    这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...

  8. java基础之 数据类型 & 值传递 引用传递 & String & 四种引用类型

    一.Java数据类型 分为基本数据类型与引用数据类型 基本数据类型: byte:Java中最小的数据类型,在内存中占1个字节(8 bit),取值范围-128~127,默认值0 short:短整型,2个 ...

  9. Java魔法堂:四种引用类型、ReferenceQueue和WeakHashMap

    一.前言 JDK1.2以前只提供一种引用类型——强引用 Object obj = new Object(); .而JDK1.2后我们多另外的三个选择分别是软引用 java.lang.ref.SoftR ...

随机推荐

  1. ORACLE11g中毒恢复

    很不幸的,win2003server疏于管理,中毒了,清理了病毒以后.oracle也瘫痪了.上次备份还在一周前,这一周的数据咋办? 首先的想法,是另找一台机器,装个一模一样的oracle.再把被删的文 ...

  2. 修改ultisnips的默认键

    把ultisnips修改和textmate一致. <tab>展开代码,再按<tab>跳转到下一个占位符,<shift+tab>跳转上一个占位符. 在vim配置文件中 ...

  3. 为debian8.2更换官方源

    最近,配置一个韩国vps,里面用的是163的源,感觉不如官方的好用,就改为官方源.地址为:ftp.cn.debian.org 输入命令: vi /etc/apt/sources.list 进入vi编辑 ...

  4. 深度学习FPGA实现基础知识10(Deep Learning(深度学习)卷积神经网络(Convolutional Neural Network,CNN))

    需求说明:深度学习FPGA实现知识储备 来自:http://blog.csdn.net/stdcoutzyx/article/details/41596663 说明:图文并茂,言简意赅. 自今年七月份 ...

  5. [k8s]kubeadm k8s免费实验平台labs.play-with-k8s.com,k8s在线测试

    k8s实验 labs.play-with-k8s.com特色 这玩意允许你用github或dockerhub去登录 这玩意登录后倒计时,给你4h实践 这玩意用kubeadm来部署(让你用weave网络 ...

  6. RednaxelaFX写的文章/回答的导航帖

    https://www.zhihu.com/people/rednaxelafx/answers http://hllvm.group.iteye.com/group/topic/44381#post ...

  7. FZU Problem 2105 Digits Count

    Problem Description Given N integers A={A[0],A[1],...,A[N-1]}. Here we have some operations: Operati ...

  8. 通过命令来查看NameNode的状态(是Active还是Standby)

    通过浏览器虽然可以查看HDFS的NameNode的状态,如果感觉不方便,可以直接使用命令来查看(前提是HDFS已经启动): [root@hadoop01 ~]# hdfs haadmin -getSe ...

  9. emWin教程目录汇总

    目录 第一章: 当前主流的小型嵌入式 GUI 第2章 初学 emWin 的准备工作及其快速上手

  10. python 字符和数值转换

    # python 字符和数值转换 ### 字符转数值------------------------------ ord('A') ==> 65- ord('B') ==> 66- ord ...