为了账号安全,请及时绑定邮箱和手机立即绑定

弱引用可维护性

弱引用可维护性

不负相思意 2021-07-27 21:18:51
我正在阅读 java 中的弱引用,听起来很简单,如果一个对象只有弱引用,那么它可以被垃圾收集器收集。除了如果您的引用在使用该值之前失效会发生什么?例子:假设我有一个键为 {1,2,3,4,5} 的弱哈希映射,所有值都为 1。现在假设您有一个用于 [1:10] 中数字的随机数生成器。现在每次得到这个数字时,它都会检查它是否是映射中的一个键,然后给出一个对该键的临时强引用。因此,通过此设置,您将拥有一些具有强引用的键,因此会留在内存中,但您也有可能在选择之前某些键已失效。如果我对弱哈希映射的直觉是正确的,那是否意味着映射将在某个时候从其原始状态改变?
查看完整描述

3 回答

?
慕神8447489

TA贡献1780条经验 获得超1个赞

尝试使用Integer对象作为 a 的键WeakHashMap可能会导致一些奇怪的行为。首先,javadoc forWeakHashMap有以下注释:

此类主要用于其等于方法使用 == 运算符测试对象身份的关键对象。一旦这样的键被丢弃,它就永远不会被重新创建,所以以后不可能在 WeakHashMap 中查找该键,并且会惊讶于它的条目已被删除。此类将与关键对象完美配合,这些对象的 equals 方法不基于对象标识,例如 String 实例。然而,对于这种可重新创建的键对象,自动删除键已被丢弃的 WeakHashMap 条目可能会令人困惑。

考虑以下代码:

   WeakHashMap<Integer, String> map = new WeakHashMap<>();

    Integer k = Integer.valueOf(9001);

    map.put(k, "OVER 9000!?");


    while (true)

    {

        System.out.println(map.get(k));

        Thread.sleep(100);

        k = Integer.valueOf(9001);

        System.gc();

    }

循环将从打印“OVER 9000!?”开始,但在第一个循环之后,原始键已被丢弃(即使现在有一个equals对它的键的引用)。结果,如果该键对象被垃圾收集,则条目将从地图中删除,并且循环将开始打印“null”。由于我们System.gc();在丢弃密钥后调用,因此这很可能发生在单个循环之后。


但这并不是Integer作为WeakHashMap密钥使用的问题的结束。如果将上面的值 9001 更改为 1,您会发现行为发生了变化!(可能?这可能取决于实现。)现在,条目永远不会从地图中删除。这是因为整数缓存——Integer.valueOf(1)总是返回相同的Integer实例,但每次都会Integer.valueOf(9001)创建一个新Integer实例。


第二个问题特定于Integer,但第一个问题实际上适用于您尝试在equals不基于 的情况下使用密钥的任何方案==。如果equals 是基于==,那么你的问题并没有真正适用-如果你没有很强的参考钥匙了,也不要紧,是否值被从地图上删除,因为你不再有办法得到它——你不能重新创建一个使用基于身份的平等的密钥。



查看完整回答
反对 回复 2021-07-29
  • 3 回答
  • 0 关注
  • 145 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信