弱引用通过WeakReference类实现,弱引用和软引用很像,但弱引用的引用级别更低。对于只有弱引用的对象而言,当系统垃圾回收机制运行时,不管系统北村是否足够,总会回收该对象所占用的内存。当然,并不是说当一个对象只有弱引用时,它就会立即被回收-正如那些失去引用的对象一样,必须等到系统垃圾回收机制运行时才会被回收。
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
public class WeakReferenceTest {
public static void main(String[] args){
Stringstr = newString("Java");
Stringstr1 = newString("Java");
SoftReference<String>sr = newSoftReference<String>(str1);
WeakReference<String>wr = newWeakReference<String>(str);
str= null;
str1= null;
System.out.println(sr.get());
System.out.println(wr.get());
System.gc();
System.runFinalization();
System.out.println(sr.get());
System.out.println(wr.get());
}
}
Output:
Java
Java
Java
null
不要使用String str = “Java”;这样就看不到运行效果,因为采用这样定义的字符串系统会缓存这个字符串直接量(会使用强引用来引用它),系统不会回收被缓存的字符串常量。
弱引用具有很大的不确定性,因为每次垃圾回收机制执行时都会回收弱引用的对象,而垃圾回收机制的运行又不受程序员的控制,因此程序获取弱引用所引用的Java对象时必须小心空指针异常-通过弱引用所获取的Java对象可能是null.
由于垃圾回收的不确定性,当程序希望从弱引用中取出被引用对象时,可能这个被引用对象已经被释放了。如果程序需要使用那个被引用的对象,则必须重新创建新对象。
public class WeakReferenceTest {
public static void main(String[] args){
Stringstr = newString("Java");
Stringstr1 = newString("Java");
SoftReference<String>sr = newSoftReference<String>(str1);
WeakReference<String>wr = newWeakReference<String>(str);
str= null;
str1= null;
System.out.println(sr.get());
System.out.println(wr.get());
System.gc();
System.runFinalization();
if(wr.get() == null){
str= new String("Java");
wr= newWeakReference<String>(str);
System.out.println(wr.get());
}
System.out.println(sr.get());
System.out.println(wr.get());
}
}
Output:
Java
Java
Java
Java
Java
与weakReference功能类似的还有WeakHashMap,当程序有大量的java对象需要使用弱引用来引用时,可以考虑使用weakHashMap来保存它们。
import java.util.WeakHashMap;
class CrazyKey{
String name;
public CrazyKey(String name){
this.name =name;
}
public inthashCode(){
return name.hashCode();
}
public boolean equals(Object obj){
if(obj==this){
returntrue;
}
if(obj!=null && obj.getClass() == CrazyKey.class){
returnname.equals(((CrazyKey)obj).name);
}
returnfalse;
}
public String toString(){
return "CrazyKey[name=" + name +"]";
}
}
public class WeakHashMapTest {
public static void main(String[] args)throws InterruptedException{
WeakHashMap<CrazyKey,String>map = newWeakHashMap<CrazyKey,String>();
for(int i=0;i<10;i++){
map.put(new CrazyKey(i+1+""),"value"+(i+11));
}
System.out.println(map);
System.out.println(map.get(new CrazyKey("2")));
System.gc();
Thread.sleep(50);
System.out.println(map);
System.out.println(map.get(new CrazyKey("2")));
}
}
Output:
{CrazyKey[name=8]=value18,CrazyKey[name=9]=value19, CrazyKey[name=4]=value14, CrazyKey[name=5]=value15,CrazyKey[name=6]=value16, CrazyKey[name=7]=value17, CrazyKey[name=10]=value20,CrazyKey[name=1]=value11, CrazyKey[name=2]=value12, CrazyKey[name=3]=value13}
value12
{}
null
在垃圾回收机制运行之前,WeakHashMap的功能与普通HashMap并没有太大的区别,它们的功能相似。但一旦垃圾回收机制被执行,WeakHashMap中所有key-value就都会被清空,除非某些Key还有强引用在引用它们。