我一直在沉思這一段時間:在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