2016-03-26 93 views
2

經常聲稱Object.hashCode()(所有對象的默認實現)的實現給出了對象的內存地址。這種說法通常附在對由Object.to String()產生的特殊輸出的解釋上。Object.toString或Object.hashCode是否提供了對象的內存地址

查看here爲例。

這當然是不是我知道任何JVM/JRE的情況。尤其是因爲現在地址通常是64位。但是,垃圾收集器也會重新定位對象,所以地址會發生變化。我見過聲稱它可以是的初始內存地址。但是,隨着許多對象將具有相似的地址,那麼對於散列碼來說這將是一個糟糕的選擇。

是否存在或曾經存在任何廣泛使用的JVM/JRE,它們是對象的(初始)內存地址。

我知道,Object類的JavaDoc表明實現的hashCode可能是內存地址。但我懷疑這是一個從未更新過的嚴重過時陳述。

事實上,當前的Oracle JVM不使用的內存地址(但可以被配置爲這樣做):

https://stackoverflow.com/a/16105878/545127

有觀點認爲,哈希碼是內存地址是一個歷史的假象:

https://stackoverflow.com/a/13860488/545127

我的問題是任何廣泛使用JVM是否(和)使用的內存地址爲(默認)implementa灰。

+2

在熱點它是可配置:https://stackoverflow.com/questions/16105420/java-object-hashcode-address-or-random/16105878#16105878 – Boann

+0

推測當時jvadoc被修改爲包含該句子的Sun JVM? (你的意思是問是否有任何*當前* JVMs這樣做?) – meriton

+0

參見http://stackoverflow.com/questions/13860194/what-is-an-internal-address-in-java – Raedwald

回答

2

由於對象的默認哈希碼不需要是唯一的,所以不需要返回整個地址。一個實現可以從地址中獲取一組比特 - 比如64位系統上的第3位到第35位,或者高32位與低32位之間的異或,或者簡單地低32位。

但是,隨着許多對象將有類似的地址[由於垃圾收集],這將是一個哈希代碼糟糕的選擇。

數字上彼此接近的哈希碼是可以的。即使少數相同的哈希碼也不會產生問題,因爲使用等式來解決任何關係。使用缺省哈希碼實現的情況通常是有限的,因爲在基於哈希的容器中用作關鍵字的對象預計會提供方法的「良好」實現。

甲骨文表示,他們的JVM的默認實現使用對象的內部地址,無論如何計算它的hashCode。然而,這樣做並不需要其他JVM實現:

這裏是一個quote from Oracle's documentation

儘可能多是合理可行的,通過Object類定義的hashCode方法不會返回針對不同的對象不同的整數。 (這一般是通過將該對象的內部地址轉換成一個整數來實現的,但不是由Java™編程語言不需要這種實現技巧。)

你可以找到實際執行的算法here的。有關詳細信息,請搜索get_next_hash函數。看來基於地址計算哈希值與一個簡單的轉換完成:

value = intptr_t(obj) ; 
+0

那是關於內部地址的聲明*實際上是真實的*。我見過(對不起,沒有參考)一篇文章,否則說。 – Raedwald

+0

@Raedwald這是一個複製粘貼[直接從馬的嘴](http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode%28%29) – dasblinkenlight

+0

低32位是一個糟糕的選擇,因爲對象地址將在字邊界上對齊。 – Raedwald

相關問題