2016-07-20 97 views
3

我處於一種情況,我有一個靜態列表緩存一些引用。由於這是一個靜態列表,我想使用WeakReference,因此我不會無用地將我的對象保存在內存中。弱引用和匿名類

問題 - 我想 - 我的是,其中一個引用是一個匿名類。我的擔心是,如果我將匿名類作爲WeakReference存儲,它可能會很快收集,如果我將匿名類作爲強引用存儲,它將持有對構建匿名類的類的引用。

我不知道我的解釋是明確的,所以這裏是一段代碼:

public interface Callback { 
    void call(); 
} 

public class A { 
    public void doIt() { 
     B.register(this, new Callback() { 
      public void call() { 
       // do something 
      } 
     }); 
    } 
} 

public class B { 
    private static final List<Item> ITEMS = new LinkedList<>(); 

    public static void register(Object key, Callback callback) { 
     Item item = new Item(); 
     item.key = new WeakReference<>(key); 

     // ?? 
     item.callback = new WeakReference<>(callback); 

     ITEMS.add(item); 
    } 

    private static class Item { 
     private WeakReference<Object> key; 
     private WeakReference<Callback> callback; 
    } 
} 

基本上,如果在項目「回調」是一個弱引用,它可能是垃圾我之前收集的甚至有機會使用它。 如果在Item'callback'中是標準引用,那麼'A'的實例永遠不會被垃圾收集。

所以我的第一個問題:我的理解是正確的嗎? 第二個問題:有沒有辦法讓它工作,或者我必須改變設計?

謝謝。

回答

1

如果Callback是一個功能接口,則可以使用lambda代替。 Lambdas只捕獲它們引用的變量。所以如果lambda是一個純函數,一個靜態方法引用或僅引用局部變量,它將不會捕獲this。如果您引用this,則會捕獲實例方法或實例字段。

通過將靜態內部類或單獨的類替換爲匿名類可以實現同樣的效果。

目前還不清楚爲什麼你使用兩個單獨的弱引用每Item。你可以簡單地將物品本身保留在一個弱參考中,並且對keycallback有很強的參考,當物品本身只能弱到達時,它們會非常弱。

一般來說,你應該推測GC根源的路徑。如果只有一個引用路徑的GC根目錄才能訪問某個對象,即使其中一個引用很弱,那麼整個子圖也只能很弱地訪問,因此有資格收集。

基本上,只有當'A'需要發佈時才能發佈我的物品。

然後一個WeakHashMap<A, Callback>是你想要的。只要確保Callback不參考A

+0

哦,我不知道lambda表達式並沒有保持這個實例,有趣。而且你是對的,我還沒有想過將整個項目作爲一個弱點參考!好的解決方案謝謝! – Tiller

+0

現在我想到了,如果我用弱引用存儲我的項目,是不是與將我的回調存儲爲弱引用時一樣存在問題?我的意思是在我有機會使用它之前收集這個項目。我知道這個原則與弱引用(你不知道什麼時候會被收集),但我想盡可能保留我的項目。基本上,只有當'A'需要發佈時才能發佈我的產品。我是否在過度追求,而且我還會沒事,因爲經常沒有收集軟弱的裁判? (SoftReference會有所作爲嗎?) – Tiller