来源:http://www.bjsxt.com/
1、S02E132_01引用(强软弱虚)、WeakHashMap、IdentityHashMap与EnumMap
(1)引用分类
——强引用(StrongReference):引用指向对象,gc(Garbage collection)运行时不回收。比如说字符串常量池,字符串可以共享,别人可能还要用
——软引用(SoftReference):gc运行时可能回收(jvm内存不够)。可用于制作缓存,对于常用的数据,敏感的数据不需要经常获取,可缓存下来
——弱引用(WeakReference):gc运行时立即回收
——虚引用(PhantomReference):类似于无引用,主要跟踪对象被回收的状态,不能单独使用,必须与引用队列(ReferenceQueue)联合使用
——目的:避免对象长期驻留在内存中,解决垃圾回收机制回收时机问题
package com.test.reference;
import java.lang.ref.WeakReference;
/**
* 引用类型:强、软、弱、虚
* <br>强与弱引用
*/
public class TestReference {
public static void main(String[] args) {
test0();
test1();
}
/**
* 字符串常量池 共享(不能被回收)
*/
public static void test0(){
String str = "very good";
//弱引用管理对象
WeakReference<String> wr = new WeakReference<String>(str);
System.out.println("gc运行前:" + wr.get());
//断开引用
str = null;
//通知回收
System.gc();
System.runFinalization();
//没有被回收
System.out.println("gc运行后:" + wr.get());
}
/**
* 字符串对象在堆中,会被回收
*/
public static void test1(){
String str = new String("very good");
//弱引用管理对象
WeakReference<String> wr = new WeakReference<String>(str);
System.out.println("gc运行前:" + wr.get());
//断开引用
str = null;
//通知回收
System.gc();
System.runFinalization();
//对象被回收
System.out.println("gc运行后:" + wr.get());
}
}
(2)WeakHashMap:键为弱引用,回收键后自动删除key-value对象(常量池的还是不会被回收)
package com.test.reference;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
public class TestWeakHashMap {
public static void main(String[] args) {
testWeakHashMap();
testHashMap();
}
/**
* 测试WeakHashMap的垃圾回收,键为弱引用,gc运行时立即被回收(常量池的还是不会被回收)
*/
public static void testWeakHashMap(){
Map<String, String> map = new WeakHashMap<String, String>();
//常量池对象,不会被回收
map.put("a", "1");
map.put("b", "2");
//gc运行时被回收
map.put(new String("c"), "3");
map.put(new String("d"), "4");
//通知回收
System.gc();
System.runFinalization();
//最后两个被回收
System.out.println(map.size());//返回2
}
/**
* 测试HashMap的垃圾回收
*/
public static void testHashMap(){
Map<String, String> map = new HashMap<String, String>();
//常量池对象,不会被回收
map.put("a", "1");
map.put("b", "2");
//gc运行时也不会被回收
map.put(new String("c"), "3");
map.put(new String("d"), "4");
//通知回收
System.gc();
System.runFinalization();
//全部不被回收
System.out.println(map.size());//返回4
}
}
(3)IdentityHashMap:键只比较地址去重,而不比较hashcode与equals;注意:键是常量池中的字符串,同值同址
package com.test.TestIdentityHashMap;
import java.util.IdentityHashMap;
import java.util.Map;
public class TestIdentityHashMap {
public static void main(String[] args) {
Map<String, String> map = new IdentityHashMap<String, String>();
//常量池中的"a",一个地址
map.put("a", "1");
map.put("a", "2");
//两个对象,两个地址
map.put(new String("a"), "3");
map.put(new String("a"), "4");
System.out.println(map.size());//返回3
}
}
(4)EnumMap:键必须为枚举的值;构造器public EnumMap(指定枚举class对象)
package com.test.reference;
import java.util.EnumMap;
import java.util.Map;
public class TestEnumMap {
//季节枚举
enum Season{SPRING,SUMMER,AUTUMN,WINTER};
public static void main(String[] args) {
Map<Season, String> map = new EnumMap<Season, String>(Season.class);
map.put(Season.SPRING, "春困");
map.put(Season.SUMMER, "夏无力");
map.put(Season.AUTUMN, "秋乏");
map.put(Season.WINTER, "冬眠");
System.out.println(map.size());//返回4
}
}