我一直在沉思这一段时间:在CLR或Java中究竟是如何实现Object.GetHashCode
?该方法的契约是,如果它在同一个对象实例上被调用,它应该总是返回相同的值。如何在CLR和JVM中实现Object.GetHashCode()?
请注意,我在谈论GetHashCode()的默认实现。派生类不需要重写此方法。如果他们选择不这样做,他们实质上将具有引用语义:在哈希表中使用时,默认情况下,默认情况下“默认等于”指针相等“& c。这意味着,运行时不得不在整个生命周期中为对象提供一个恒定的哈希码。
如果我运行的机器是32位的,并且如果对象实例从未在内存中移动,理论上可以返回对象的地址,重新解释为Int32。这很好,因为所有不同的对象都有不同的地址,因此会有不同的哈希码。
但是,这种方法是有缺陷的,除其他事情,因为:
如果垃圾收集器在内存中移动对象时,它的地址变化,所以会违反合同的散列码的哈希码在对象的生命周期中应该相同。
在64位系统上,对象的地址太宽,无法放入Int32。
由于被管理对象倾向于与某些偶数次幂对齐,所以最低位将始终为零。当散列码用于索引散列表时,这可能会导致分布模式不正确。
在.NET中,一个System.Object
由同步块和型手柄,仅此而已,所以哈希码不能在该实例本身缓存。不知何故,运行时能够提供持久的哈希码。怎么样? Java,Mono和其他运行时如何做到这一点?
谢谢你的回答,这很有道理。我的想法被锁定在想法上,即同步块只能存储单个东西,但是您在此处绘制的机制解释了如何将多个额外属性按需添加到对象。 – 2011-04-07 14:07:49