Java的四种引用类型之弱引用
先说结论:
首先,Java中有四种引用类型:强引用、软引用、弱引用、虚引用。-- 在 Java 1.2 中添加的,见 package java.lang.ref; 。
其次,这几个概念是与垃圾回收有关的。
然后,如果你不知道这几个概念,那你用的肯定都是强引用。例如 String str = new String(); 这个 str 到 new 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的四种引用类型之弱引用的更多相关文章
- java中四种引用类型(对象的强、软、弱和虚引用)
对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2 ...
- java中四种引用类型
java中四种引用类型 今天看代码,里面有一个类java.lang.ref.SoftReference把小弟弄神了,试想一下,接触java已经有3年了哇,连lang包下面的类都不了解,怎么混.后来在 ...
- 你知道Java的四种引用类型吗
关于java四种引用类型,我也是刚了解,特此记下! 在Java中提供了四个级别的引用:强引用,软引用,弱引用和虚引用.在这四个引用类型中,只有强引用FinalReference类是包内可见,其他三种引 ...
- java的四种引用类型
java的引用分为四个等级:4种级别由高到低依次为:强引用.软引用.弱引用和虚引用. ⑴强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回 ...
- java中四种引用类型(转)
今天看代码,里面有一个类java.lang.ref.SoftReference把小弟弄神了,试想一下,接触java已经有3年了哇,连lang包下面的类都不了解,怎么混.后来在网上查资料,感觉收获颇多, ...
- Java中的四种引用类型,强引用,软引用,弱引用,虚引用
对于Java中的垃圾回收机制来说,对象是否被回收的标准在于该对象是否被引用.因此,引用也是JVM进行内存管理的一个重要概念. Java中对象的引用一般有以下4种类型: 1强引用 2软引用 3弱引用 ...
- Java中四种引用:强、软、弱、虚引用
这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...
- java基础之 数据类型 & 值传递 引用传递 & String & 四种引用类型
一.Java数据类型 分为基本数据类型与引用数据类型 基本数据类型: byte:Java中最小的数据类型,在内存中占1个字节(8 bit),取值范围-128~127,默认值0 short:短整型,2个 ...
- Java魔法堂:四种引用类型、ReferenceQueue和WeakHashMap
一.前言 JDK1.2以前只提供一种引用类型——强引用 Object obj = new Object(); .而JDK1.2后我们多另外的三个选择分别是软引用 java.lang.ref.SoftR ...
随机推荐
- Mac - 使用php环境
按下shift + Command + G ,输入以下php(www)路径 /Library/WebServer/Documents 打开终端,输入以下命令打开环境 sudo apachectl s ...
- NodeJS写日志_Log4js使用详解
今天和大家分享一下NodeJS中写日志的一个常用第三方包:Log4js. 跟随主流Blog特色,先简单介绍下Log4js的基本信息.介绍Log4js之前,需要先说一下Log4***,Log4***是由 ...
- PS图像菜单下计算命令
PS图像菜单下计算命令通过通道的混合模式得到的选区非常精细,从而调色的时候过度非常好.功能十分强大. 下面用计算命令中的"相加"和"减去"模式做实例解析,这 ...
- Direct-X学习笔记--三维摄像机
一.介绍 哇! 到了传说中的3D摄像机啦! 之前我们写的东东,都是观察点不动,通过世界变换让东西动,今天,通过三维摄像机我们就能够改变我们的观察点,观察方向,任意在三维空间中驰骋.之前我们所设定的视角 ...
- 查杀病毒的NB命令
kill - `pgrep linux|awk '{++S[$1]}END{for (i in S) print i}'` teamkill #!/bin/bash set -x kill - `pg ...
- C++ function pointer and type cast
http://www.cprogramming.com/tutorial/function-pointers.html http://www.cplusplus.com/doc/tutorial/ty ...
- C程序的内存布局
1.代码段(code或text): 通常是指用来存放程序执行代码的一块内存区域.这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读. 某些架构也允许代码段为可写,即允许修改程序.在代码 ...
- 简单的图形学(三)——光源
参考自:用JavaScript玩转计算机图形学(二)基本光源 - Milo Yip - 博客园,主要讲述三种最基本的光源--平行光.点光源.聚光灯,其实就是三种数学模型. 代码的调整 先前的代码中,颜 ...
- CEdit 控制键盘操作
写在前面的话:在工作中要实现这样一个功能,在一个树形控件中选择要发送消息的客户,添加到一个列表控件中,点击确定跳到一个信息发送页面如下图,在发送人编辑框中显示选择的客户,要实现的就是即允许用户删除用户 ...
- java timer timertask mark
其实就Timer来讲就是一个调度器,而TimerTask呢只是一个实现了run方法的一个类,而具体的TimerTask需要由你自己来实现,例如这样: 1 2 3 4 5 6 Timer timer = ...