java 分析一道关于WeakReference的题目
题目:
import java.lang.ref.WeakReference; import java.util.WeakHashMap; public class Test1 { public static void main(String[] args) { String val = test(); System.out.println("val:" + val); } private static String test(){ String a = new String("a"); WeakReference<String> b = new WeakReference<String>(a); WeakHashMap<String, Integer> weakMap = new WeakHashMap<String, Integer>(); weakMap.put(b.get(), 1); a = null; System.gc(); String c = ""; try{ c = b.get().replace("a", "b"); return c; }catch(Exception e){ c = "c"; return c; }finally{ c += "d"; return c + "e"; } } }
该题关键在考察WeakReference和WeakHashMap的理解。
先说下一点Java GC内容
在Java里, 当一个对象object被创建时,它被放在Heap里。当GC运行的时候,如果发现没有任何引用指向object,object就会被回收以腾出内存空间。或者换句话说,一个对象被回收,必须满足两个条件:1)没有任何引用指向它 2)GC被运行.
WeakReference
当一个对象仅仅被weak reference(弱引用)指向, 而没有任何其他strong reference(强引用)指向的时候, 如果GC运行, 那么这个对象就会被回收。weak reference的语法是:
WeakReference<T> weakref = new WeakReference<T>();
当要获得WeakReference的object时, 首先需要判断它是否已经被GC回收,若被收回,则下列返回值为空:
weakref.get();
所以在上述代码中,经过a=null; System.gc()后,当代码运行到c = b.get().replace("a", "b");时,由于b.get()为null,会抛出异常。
WeakHashMap
WeakHashMap其实和HashMap用法类似,它们之间唯一的区别就是:HashMap中的key保存的是实际对象的强引用,因此只要对象不被销毁,即该key所对应的key-value都不会被垃圾回收机制回收。但是WeakHashMap保存的实际对象是弱引用,这意味着只要该对象没有被强对象引用就有可能会被垃圾回收机制回收对应的Key-value。示例如下:
import java.lang.ref.WeakReference; import java.util.WeakHashMap; public class WeakHashMapTest { public static void main(String[] args) { WeakHashMap weakMap = new WeakHashMap(); //三个key-value中的key 都是匿名对象,没有强引用指向该实际对象 weakMap.put(new String("语文"),new String("优秀")); weakMap.put(new String("数学"), new String("及格")); weakMap.put(new String("英语"), new String("中等")); //增加一个字符串的强引用 weakMap.put("java", new String("特别优秀")); System.out.println(weakMap); //通知垃圾回收机制来进行回收 System.gc(); System.runFinalization(); //再次输出w System.out.println("第二次输出:"+weakMap); } }
所以在最开始的代码中WeakHashMap<String, Integer> weakMap = new WeakHashMap<String, Integer>(); weakMap没有强引用指引,所以在执行System.gc()后weakMap被系统GC收回。