Java中關於WeakReference和WeakHashMap的理解
新美大的10月11日的筆試中有一道選擇題,讓選擇函數返回結果,代碼如下:
1 private static String test(){
2 String a = new String("a");
3 WeakReference<String> b = new WeakReference<String>(a);
4 WeakHashMap<String, Integer> weakMap = new WeakHashMap<String, Integer>();
5 weakMap.put(b.get(), 1);
6 a = null;
7 System.gc();
8 String c = "";
9 try{
10 c = b.get().replace("a", "b");
11 return c;
12 }catch(Exception e){
13 c = "c";
14 return c;
15 }finally{
16 c += "d";
17 return c + "e";
18 }
19 }
運行結果是“cde”。
該題關鍵在考察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.util.WeakHashMap;
public class WeakHashMapTest {
public static void main(String[] args) {
WeakHashMap w= new WeakHashMap();
//三個key-value中的key 都是匿名對象,沒有強引用指向該實際對象
w.put(new String("語文"),new String("優秀"));
w.put(new String("數學"), new String("及格"));
w.put(new String("英語"), new String("中等"));
//增加一個字符串的強引用
w.put("java", new String("特別優秀"));
System.out.println(w);
//通知垃圾回收機制來進行回收
System.gc();
System.runFinalization();
//再次輸出w
System.out.println("第二次輸出:"+w);
}
}
輸出結果:{java=特別優秀, 數學=及格, 英語=中等, 語文=優秀}
第二次輸出w:{java=特別優秀}
所以在最開始的代碼中WeakHashMap<String, Integer> weakMap = new WeakHashMap<String, Integer>(); weakMap沒有強引用指引,所以在執行System.gc()後weakMap被系統GC收回。
打印出代碼中的變量
1 private static String test(){
2 String a = new String("a");
3 //System.out.println(a);
4 WeakReference<String> b = new WeakReference<String>(a);
5 //System.out.println(b.get());
6 WeakHashMap<String, Integer> weakMap = new WeakHashMap<String, Integer>();
7 weakMap.put(b.get(), 1);
8 a = null;
9 System.out.println("GC前b.get():"+b.get());
10 System.out.println("GC前weakMap:"+weakMap);
11 System.gc();
12 System.out.println("GC後"+b.get());
13 System.out.println("GC後"+weakMap);
14 String c = "";
15 try{
16 c = b.get().replace("a", "b");
17 System.out.println("C:"+c);
18 return c;
19 }catch(Exception e){
20 c = "c";
21 System.out.println("Exception");
22 return c;
23 }finally{
24 c += "d";
25 return c + "e";
26 }
27 }
運行後結果為:
GC前b.get():a
GC前weakMap:{a=1}
GC後null
GC後{}
Exception
cde
可見,在System.gc()前後的WeakReference和WeakHashMap的變化。
Java中異常處理中try,catch,finally的關系
java 的異常處理中,
在不拋出異常的情況下,程序執行完 try 裏面的代碼塊之後,該方法並不會立即結束,而是繼續試圖去尋找該方法有沒有 finally 的代碼塊,
如果沒有 finally 代碼塊,整個方法在執行完 try 代碼塊後返回相應的值來結束整個方法;
如果有 finally 代碼塊,此時程序執行到 try 代碼塊裏的 return 語句之時並不會立即執行 return(如果return後是語句或者函數,eg:return b+=10; or return functionA();,先執行return後的語句或者函數),而再去執行 finally 代碼塊裏的代碼,
若 finally 代碼塊裏沒有 return 或沒有能夠終止程序的代碼,程序將在執行完 finally 代碼塊代碼之後再返回 try 代碼塊執行 return 語句來結束整個方法;
若 finally 代碼塊裏有 return 或含有能夠終止程序的代碼,方法將在執行完 finally 之後被結束,不再跳回 try 代碼塊執行 return。
在拋出異常的情況下,原理也是和上面的一樣的,你把上面說到的 try 換成 catch 去理解就 OK 了。
現在分析上述代碼:
System.gc()後b.get()和weakMap均為null
try中拋出異常,在catch中捕獲異常
執行c = "c",執行到return c,但是並不立即return,執行finally
執行 c +="d"; return c + "e",finally代碼塊中有return語句就不會返回catch中執行return了。
所以最終結果是return "cde"
==============================
轉載:http://www.cnblogs.com/Skyar/p/5962253.html
Java中關於WeakReference和WeakHashMap的理解