弱引用和匿名类

时间:2016-07-20 10:02:06

标签: java garbage-collection weak-references

我的情况是我有一个静态列表缓存一些引用。由于这是一个静态列表,我想使用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;永远不会被垃圾收集。

所以我的第一个问题是:我的理解是对的吗? 第二个问题:有没有办法让它工作或者我必须改变设计?

感谢。

1 个答案:

答案 0 :(得分:1)

如果Callback是功能接口,则可以使用lambda。 Lambdas只捕获它们引用的变量。因此,如果lambda是纯函数,静态方法引用或仅引用局部变量,则它不会捕获this。如果您引用this,实例方法或实例字段,则它将捕获。

通过将静态内部类或单独的类替换为匿名类,可以实现同样的目的。

目前还不清楚为什么每个Item使用两个单独的弱引用。您可以简单地将项目本身保留在弱引用中,并且对keycallback具有强烈的引用,当项目本身只能微弱地到达时,它们将非常弱。

一般来说,你应该推断GC根的路径。如果一个对象只能从具有引用路径的GC根目录到达,即使其中一个引用也很弱,那么整个子图只能是弱可达的,因此有资格进行收集。

  

基本上,只有在需要释放“A”时才释放我的项目。

然后WeakHashMap<A, Callback>就是你想要的。只需确保Callback未引用A