如果一个WeakHashMap的值包含对键的唯一强引用,那么该条目是否会被收集?

9
我需要将一些数据与一个键关联,以便在其生命周期内使用,因此我正在使用 WeakHashMap。然而,除此之外,我还需要通过相应的值获取键。做法很简单,创建值时保留引用即可:
public class Key {}

public class Value { 
    final public Key key;
    public Value(Key k) {
        key = k;
    }
}

当我在程序中使用“Value”时,“key”并不会消失。然而,如果除了地图之外再也没有关于“key”或其“value”的引用,它会被垃圾回收吗?还是“value”中存活的强引用会阻止它被回收?
2个回答

15
不,它不会被垃圾回收,参见Javadoc
实现注意事项:WeakHashMap中的值对象由普通强引用持有。因此,应当确保值对象不会直接或间接地强引用其自身的键,否则将阻止键被丢弃。
如@biziclop所述,一种解决方案是在您的值对象中存储对键的弱引用。
public class Value { 
  final public WeakReference<Key> key;
  public Value(Key k) {
    this.key = new WeakReference<Key>(k);
  }
}

@biziclop 还有从Javadoc中得知的:处理这个问题的一种方法是在插入之前将值本身包装在WeakReferences中,例如:m.put(key, new WeakReference(value)),然后在每次获取时进行解包。 这样就可以解决问题了! - laguille
1
要么只在值对象中存储对键的弱引用,否则就将键包装在一个WeakReference中。因为如果您将值包装在WR中,可能会出现已收集该值的现有键的情况。 - biziclop

2

从实现上看,答案似乎是否定的。

这是来自于 WeakHashMap 的源代码:

/**
 * The table, resized as necessary. Length MUST Always be a power of two.
 */
private Entry[] table;

...

private static class Entry<K,V> extends WeakReference<K> implements Map.Entry<K,V> {
    private V value;
    ...
}

正如您所看到的,Entry对象被地图本身强烈引用。因此,如果地图可访问,则Entry也将可访问,因此您的Value对象和键也将可访问。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接