我的情况是我有一个静态列表缓存一些引用。由于这是一个静态列表,我想使用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&#39; callback&#39;是一个弱参考,它可能是垃圾收集之前,我甚至有机会使用它。 如果在Item&#39; callback&#39;是标准参考,A&#39; A&#39;永远不会被垃圾收集。
所以我的第一个问题是:我的理解是对的吗? 第二个问题:有没有办法让它工作或者我必须改变设计?
感谢。
答案 0 :(得分:1)
如果Callback
是功能接口,则可以使用lambda。 Lambdas只捕获它们引用的变量。因此,如果lambda是纯函数,静态方法引用或仅引用局部变量,则它不会捕获this
。如果您引用this
,实例方法或实例字段,则它将捕获。
通过将静态内部类或单独的类替换为匿名类,可以实现同样的目的。
目前还不清楚为什么每个Item
使用两个单独的弱引用。您可以简单地将项目本身保留在弱引用中,并且对key
和callback
具有强烈的引用,当项目本身只能微弱地到达时,它们将非常弱。
一般来说,你应该推断GC根的路径。如果一个对象只能从具有引用路径的GC根目录到达,即使其中一个引用也很弱,那么整个子图只能是弱可达的,因此有资格进行收集。
基本上,只有在需要释放“A”时才释放我的项目。
然后WeakHashMap<A, Callback>
就是你想要的。只需确保Callback
未引用A
。