弱引用通過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還有強引用在引用它們。