这个答案已经解决了在构造中使用具有基于值的相等类型的问题,该构造的行为取决于对象的身份,例如可达性。
简而言之,当您能够构造与弱可达键具有相同相等性的新对象时,就有可能检测到键的突然移除。
但是,您也可以将弱可达对象转回强可达状态,例如通过调用get()
a 的方法WeakReference
或在迭代 a 的映射时WeakHashMap
。
WeakHashMap<Object, Boolean> map = new WeakHashMap<>();
Object key = new Object();
map.put(key, true);
WeakReference<Object> ref = new WeakReference<>(key);
key = null;
// now, the key object is only weakly reachable
key = ref.get();
// now, the key object might be strongly reachable again
// in that case, this statement will print true
System.out.println(map.get(key));
具有不同标识且没有覆盖equals
方法 via的对象的构造new Object()
可确保不存在对同一对象的其他引用或相等对象。在这段代码的某一时刻,该对象只是弱可达,但随后,它以非常高的可能性变得强可达。
在这些点之间可能会发生垃圾收集,并且由于对对象的所有弱引用都被自动清除,因此您可以通过null
从get()
. 不过,此时发生垃圾收集的可能性非常低。这就是为什么链接的答案使用中间调用来System.gc()
提高弱引用被清除的可能性。
这是一个相当人为的例子,但有助于解决您的问题,“......这是否意味着地图将在某个时候从其原始状态改变?”。
如果您使用具有不同身份的相同键或在一段时间内难以访问的键,则映射可能会在某个时候更改,但不能保证这种情况会发生。这取决于垃圾收集器何时运行并实际发现某些对象的弱可达性。但通常,JVM 会尝试阻止垃圾收集,直到真正需要它为止。因此,应用程序可能会在没有垃圾收集的情况下安静地运行一段时间。此外,如果您确实定期轮询映射,甚至可能发生 gc 在查找期间键可强烈访问的那个时间点运行。