在java 中除了基本数据类型之外,其他都是引用数据类型,而引用数据类型又分类四种
强引用
指向通过new得到的内存空间的引用叫做强引用,比如 String a = new String(“123”),其中的a就是一个强引用,它指向了一块内存为123的堆空间。平时我们用的最多的也是强类型.
软引用
软引用(在java 中可以用SoftReference类实现)的含义是,如果一个 对象 具有软引用,如果虚拟机内存不足或发生oom之前,JVM虚拟机会回收这些被软引用指向的内存区域,如果内存足够,便不会回收。一般用于存放较为敏感的信息。
弱引用
弱引用和软引用较为相识(通过WeakReference类实现),他们的区别在于,垃圾回收器一旦发现某块内存上有且仅有弱引用(一定要注意只有弱引用,没有强引用)指向这块内存的地址空间,不管当前内存是否足够,这这块被弱引用指向的内存空间都会GC回收。
虚引用
虚引用也叫幻象引用,通过PhantomReference类来实现,无法通过虚引用访问对象的任何属性和函数,虚引用只是提供了了一种确保对象在finalize以后可以做某些事情的机制。(目前学习阶段没接触到如何使用它,以后碰到了再补充一篇)
下面我们看看这软引用和弱引用之间的区别
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
/**
* 引用区别
*
* @author koala
* @date 2018/5/26
*/
public class ReferenceDemo {
public static void main(String[] args) {
/**
* str 指向堆内存内容为abc的地址
*/
String str = new String("abc");
// 软引用
SoftReference<String> softReference = new SoftReference<String>(str);
str = null;
System.gc();
System.out.println(softReference.get()); // 执行结果: abc
String abc = new String("123");
// 弱引用
WeakReference<String> weekReference = new WeakReference<String>(abc);
// 去掉强引用
abc = null;
System.gc();
System.out.println(weekReference.get()); // 执行结果: null
}
}
,一般软软引用可以做一些缓存处理,如果不使用第三方缓存机制,可以使用软引用实现缓存方案,比如,文章缓存(从软引用里面去取文章内容,如果没有再从数据库中取,在刷回到软引用中)
我们来使用WeakHashMap来了解弱引用的使用场景
“`
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
/**
* 弱引用对象
*
* @author koala
* @date 2018/5/26
*/
public class WeekHashMapDemo {
public static void main(String[] args) {
/**
* // 假设堆空间为1000 A
*
* a -> A
*
*/
String a = new String("ABC");
/**
* // 假设堆空间为2000 B
*
* b -> B
*
*/
String b = new String("123");
Map weakMap = new WeakHashMap();
Map map = new HashMap(10);
/**
* a - > A -- 强引用
* map:(AAA) - > A -- 强引用
*
* b - > B -- 强引用
* map: (BBB) - > B -- 强引用
*/
map.put(a,"AAA");
map.put(b,"BBB");
/**
* a - > A -- 强引用
* map:(AAA) - > A -- 强引用
* weakmap:(aaa) -> A -- 弱引用
*
* b - > B -- 强引用
* map: (BBB) - > B -- 强引用
* weakmap:(bbb) -> B -- 弱引用
*/
weakMap.put(a,"aaa");
weakMap.put(b,"bbb");
/**
* a - > A -- 强引用
* weakmap:aaa -> A -- 弱引用
*
* b - > B -- 强引用
* map: BBB - > B -- 强引用
* weakmap:bbb -> B -- 弱引用
*/
map.remove(a);
/**
* weakmap:aaa -> A -- 弱引用
*
* map: BBB - > B -- 强引用
* weakmap:bbb -> B -- 弱引用
*/
a = null;
b = null;
System.gc();
/**
* 输出结果
* map,123:BBB
*
* 分析, 在gc之前,map集合a引用已经被移除,只有一个b引用是一个强类型
*/
System.out.println(a);
Iterator i = map.entrySet().iterator();
while (i.hasNext()){
Map.Entry en = (Map.Entry) i.next();
System.out.println("map,"+en.getKey()+":"+en.getValue());
}
/**
* 输出结果
* weakmap,123:bbb
*
* 分析:weakmap集合key值为a的引用(指向地址A)是一个弱引用,gc会回收被弱引用所引用的对象,所以A地址空间会被回收(A地址中只有被弱引用引用)
* weakmap集合key值为b的引用,由于在map集合中有强引用指向地址B,及时weakmap中key值为b弱引用,指向这个地址空间,此地址空间也不会被回收
*
*/
Iterator j = weakMap.entrySet().iterator();
while (j.hasNext()){
Map.Entry en = (Map.Entry) j.next();
System.out.println("weakmap,"+en.getKey()+":"+en.getValue());
}
}
}
无论是软引用还是弱引用获取虚引用都可以使用引用队列ReferenceQueue配合使用,可以通过程序判断是否加入了某些引用,那些引用被回收了,从而我们可以在引用回收之前采取一些程序行动