@(java)java
public native int hashCode(); public boolean equals(Object obj) { return (this == obj); } public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
能夠發現咱們打印的是調用對象的對應Class對象的getName()方法返回值和hashcode()方法的16進製表示。程序員
native方法指原生態方法,它調用的不是java語言,而是其餘語言,好比C語言。
閱讀hashCode的spec,咱們發現根本沒有說起其實現方式編程
/ **
返回對象的哈希碼值。這種方法是
支持哈希表的好處,例如那些提供的哈希表
* {@link java.util.HashMap}。
* {hashCode}的通常合約是:
* 每次在同一個對象中調用屢次
執行Java應用程序,即{hashCode}方法
必須始終返回相同的整數,不提供任何信息
用於在對象上進行修改的{@code equals}比較。
這個整數不須要從一個執行中保持一致
應用程序到另外一個執行相同的應用程序。
若是根據equals(Object)}兩個對象相等
方法,而後在每一個方法上調用{@code hashCode}方法
這兩個對象必須產生相同的整數結果。
* 若是兩個對象不相等,則不須要
根據{@link java.lang.Object#equals(java.lang.Object)}
方法,而後在每一個方法上調用{@code hashCode}方法
兩個對象必須產生不一樣的整數結果。可是,那
程序員應該知道產生不一樣的整數結果
用於不相等的對象能夠提升散列表的性能。
儘量合理實用,由。定義的hashCode方法
* class {@code Object}確實爲不一樣的返回不一樣的整數
對象。 (這一般經過轉換內部來實現
對象的地址轉換爲整數,可是這個實現
技術不是必需的
Java™編程語言)。
* @返回此對象的哈希碼值。
* @see java.lang.Object#equals(java.lang.Object)
參見java.lang.System#identityHashCode
/api
再參考最近幾個版本jdk的API簡介中對hashcode實現的介紹併發
從java源碼中們不能得知hashcode的具體實現方式,只知道其spec。api描述也很是曖昧。
咱們能夠推測的是jvm的設計目標包括跨平臺適用,因此其hashcode的實現應該是在各個平臺上不一樣的,或者與平臺無關。jvm
更深刻的理解應該是困難的,因此下面我整理了stack overflow的高票答案,僅供參考。請注意它的時效性,雖然我已經選取最新的,可是仍是可能有出入,建議做爲閱讀材料來處理,畢竟hashCode到底如何實現和咱們使用java無關。編程語言
在HotSpot JVM默認狀況下,第一次調用非超載Object.hashCode或System.identityHashCode隨機數時會生成並存儲在對象頭中。隨後調用Object.hashCode或System.identityHashCode僅從頭>中提取此值。默認狀況下,它與對象內容或對象位置沒有什麼共同之處,只是隨機數。此行爲由-XX:hashCode=n具備如下可能值的HotSpot JVM選項控制:ide
- 0:使用全局隨機生成器。這是Java 7中的默認設置。它具備的缺點是,來自多個線程的併發調用可能會致使爭用條件,從而致使爲不一樣對象生成相同的hashCode。並且在高度併發環境中,由>於爭用(使用來自不一樣CPU內核的相同內存區域),可能會出現延遲。
- 1:使用對象指針與一些在「世界中止」事件中更改的隨機值混合,所以在中止世界事件(如垃圾收集)生成的hashCode之間是穩定的(用於測試/調試目的)
- 2:始終使用1(用於測試/調試目的)
- 3:使用自動增長數字(爲了測試/調試目的,還使用全局計數器,所以爭用和競爭條件是可能的)
- 4:若是須要,使用修剪爲32位的對象指針(用於測試/調試目的)
- 5:使用一些沒有先前缺點的線程局部xor-shift隨機生成器。這是Java 8中的默認設置。
請注意,即便您設置了-XX:hashCode=4,hashCode也不會始終指向對象地址。對象可能會稍後移動,但hashCode將保持不變。另外,對象地址分佈不均勻(若是您的應用程序使用的內存不足,大多數對象將彼此靠近),所以若是使用此選項,最終可能會出現不平衡的哈希表。
若是hashCode()沒有被覆蓋,什麼是對象的哈希碼?
咱們從這個回答能發現,7 8兩代的默認實現形式都去除了和地址的關聯。猜想這樣的實現形式能更好的知足跨平臺的設計目標。性能
核心觀點是hashCode只能被用來判斷不相同,不能用來判斷相同,Objcet.hashCode()並無由於是Object的hashCode而有任何特殊之處。
理由很直白:不管是之內部地址生成隨機數,仍是直接使用隨機數生成器生成隨機數,其長度都被截取爲32位,必定存在重複。咱們不能認爲hashCode相同則就是同一個對象。hashCode應該被用來優化檢索,由於若是hashCode不一樣則必定不是同一對象。測試