JDK1.8 --- Object類的HashCode悦穿、equals攻礼、clone方法解析

一、public native int hashCode()

???????返回當(dāng)前對象運行時的hash碼咧党。(在jdk源碼中的解釋是用于支持散列表數(shù)據(jù)結(jié)構(gòu)秘蛔,因為散列表在進行數(shù)據(jù)存儲時依賴hash碼決定數(shù)據(jù)存儲的位置(邏輯位置)。在程序運行中傍衡,無論什么情況下深员,相同的對象對應(yīng)的hash碼一定是相同的。但是不同的對象有可能會返回相同的hash碼蛙埂。那么其實也代表如果兩個對象的hash碼不一致倦畅,這兩個對象一定是不同的。)
這里我們做一下延伸:

為什么需要Hash碼绣的?
???????Hash碼的作用:文本校驗叠赐,數(shù)字簽名。

hash碼到底是什么屡江?(這里我們引用百度百科的內(nèi)容)
???????Hash譯作“散列”芭概,就是把任意長度的輸入(又叫做預(yù)映射pre-image)通過散列算法變換成固定長度的輸出,該輸出就是散列值惩嘉。這種轉(zhuǎn)換是一種壓縮映射罢洲,也就是,散列值的空間通常遠(yuǎn)小于輸入的空間文黎,不同的輸入可能會散列成相同的輸出惹苗,所以不可能從散列值來確定唯一的輸入值。簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)耸峭。

以上有一些概念需要一一作出解釋:
常見的散列算法:

  1. 余數(shù)法:先估計整個哈希表中的表項目數(shù)目大小桩蓉。然后用這個估計值作為除數(shù)去除每個原始值,得到商和余數(shù)劳闹。用余數(shù)作為哈希值院究。因為這種方法產(chǎn)生沖突的可能性相當(dāng)大,因此任何搜索算法都應(yīng)該能夠判斷沖突是否發(fā)生并提出取代算法本涕。
  2. 折疊法:這種方法是針對原始值為數(shù)字時使用儡首,將原始值分為若干部分,然后將各部分疊加偏友,得到的最后四個數(shù)字(或者取其他位數(shù)的數(shù)字都可以)來作為哈希值蔬胯。
  3. 基數(shù)轉(zhuǎn)換法:當(dāng)原始值是數(shù)字時,可以將原始值的數(shù)制基數(shù)轉(zhuǎn)為一個不同的數(shù)字位他。例如氛濒,可以將十進制的原始值轉(zhuǎn)為十六進制的哈希值产场。為了使哈希值的長度相同,可以省略高位數(shù)字舞竿。
  4. 數(shù)據(jù)重排法:這種方法只是簡單的將原始值中的數(shù)據(jù)打亂排序京景。比如可以將第三位到第六位的數(shù)字逆序排列,然后利用重排后的數(shù)字作為哈希值骗奖。

Java中Hashcode方法的規(guī)定:

  • 在 Java 應(yīng)用程序執(zhí)行期間确徙,在對同一對象多次調(diào)用 hashCode 方法時,必須一致地返回相同的整數(shù)执桌,前提是將對象進行 equals 比較時所用的信息沒有被修改鄙皇。從某一應(yīng)用程序的一次執(zhí)行到同一應(yīng)用程序的另一次執(zhí)行,該整數(shù)無需保持一致仰挣。

  • 如果根據(jù) equals(Object) 方法伴逸,兩個對象是相等的,那么對這兩個對象中的每個對象調(diào)用 hashCode 方法都必須生成相同的整數(shù)結(jié)果膘壶。

  • 如果根據(jù) equals(java.lang.Object) 方法错蝴,兩個對象不相等,那么對這兩個對象中的任一對象上調(diào)用 hashCode方法不 要求一定生成不同的整數(shù)結(jié)果颓芭。但是顷锰,程序員應(yīng)該意識到,為不相等的對象生成不同整數(shù)結(jié)果可以提高哈希表的性能亡问。

Hotspot中hashcode方法的實現(xiàn):


圖片 1.png

???????hash方法的實現(xiàn)是先獲取該對象的標(biāo)記字對象官紫,然后對該標(biāo)記字對象的的地址做位移和邏輯與操作,以結(jié)果作為hashcode(其中玛界,mark_bits方法在globalDefinitions.hpp)万矾,之所以做移位操作是因為hashcode在標(biāo)記字中只占用了部分位(32位機器上是占用25位悼吱,64位機器上占用31)
???????從實現(xiàn)來看慎框,我們試圖解釋hashcode的一個現(xiàn)象,為什么不同的對象可能返回相同的hashcode方法后添?
因為盡管虛擬機在運行過程中笨枯,不同的對象的地址一定是不同的,但是由于hashcode需要固定25位或者31位遇西,那么就導(dǎo)致真正的hashcode值需要在對象地址上做一定的操作馅精。從而將一個大范圍區(qū)間的值映射到一個小范圍區(qū)間的值(hashcode的計算過程),這樣的操作必定會導(dǎo)致一部分?jǐn)?shù)據(jù)的計算結(jié)果會重復(fù)粱檀。所以說這就是不同的對象可能返回相同hash值的原因洲敢。

二、 public boolean equals(Object obj)

圖片 1.png

在java中equals的作用是茄蚯,判斷兩個對象是不是相等的压彭。
???????從jdk的實現(xiàn)可以看出:equals其實就是在比較兩個對象的地址是否相等睦优,所以這個方法不存在hashcode()的問題,因為對象在內(nèi)存中的地址是唯一的壮不。
重寫equals()方法就必須重寫hashCode()方法的原因汗盘。
???????假設(shè)兩個對象,重寫了其equals方法询一,其相等條件是屬性相等隐孽,就返回true。如果不重寫hashcode方法健蕊,其返回的依然是兩個對象的內(nèi)存地址值菱阵,必然不相等。這就出現(xiàn)了equals方法相等绊诲,但是hashcode不相等的情況送粱。這不符合hashcode的規(guī)則。在集合框架中掂之,這種情況會導(dǎo)致的嚴(yán)重的問題抗俄,具體的問題在hashMap中會具體分析。

三世舰、 protected native Object clone()

本地方法表
static JNINativeMethod methods[] = {
???????{"hashCode", "()I", (void *)&JVM_IHashCode},
???????{"wait", "(J)V", (void *)&JVM_MonitorWait},
???????{"notify", "()V", (void *)&JVM_MonitorNotify},
???????{"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll},
???????{"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone}
};
???????由本地方法表知道clone方法對應(yīng)的本地函數(shù)為JVM_Clone动雹,clone方法主要實現(xiàn)對象的克隆功能,根據(jù)該對象生成一個相同的新對象(我們常見的類的對象的屬性如果是原始類型則會克隆值跟压,但如果是對象則會克隆對象的地址)胰蝠。Java的類要實現(xiàn)克隆則需要實現(xiàn)Cloneable接口,if (!klass->is_cloneable())這里會校驗是否有實現(xiàn)該接口震蒋。然后判斷是否是數(shù)組分兩種情況分配內(nèi)存空間茸塞,新對象為new_obj,接著對new_obj進行copy及C++層數(shù)據(jù)結(jié)構(gòu)的設(shè)置查剖。最后再轉(zhuǎn)成jobject類型方便轉(zhuǎn)成Java層的Object類型钾虐。
源碼:


圖片 1.png

看到j(luò)vm源碼之后我們來分析一下:
???????底層在實現(xiàn)clone()方法其實非常簡單,一.首先確認(rèn)當(dāng)前對象是否實現(xiàn)了cloneable接口(這是一個標(biāo)記接口)笋庄,二.分配一個和當(dāng)前對象一樣大小的空間效扫,三.將原對象堆中的區(qū)域以字節(jié)的方式復(fù)制到新對象中。
???????然而對象在堆中的存儲直砂,對象屬性其實存儲的只是引用地址菌仁,那么使用clone()方法的時候就是我們所說淺拷貝,只是值拷貝静暂〖们穑拷貝的接口是拷貝的對象和原對象的對象屬性指向同一個地址。對這個屬性做改動時洽蛀,會互相影響摹迷。

那么引出一個問題弯院,我們怎么進行深拷貝呢?
???????解決的方法是調(diào)用對象屬性的clone()方法泪掀,需要所有的對象屬性都重寫clone()方法听绳。然后再調(diào)用上層對象的clone()方法時,再里面調(diào)用屬性的對象的clone()方法异赫,實現(xiàn)深拷貝椅挣。

還有一個值得思考的問題,String對象如何進行拷貝的塔拳?
???????String對象本身是個final類鼠证,所以在對它做拷貝的時候注定是值拷貝,拷貝之后的String和原來的String指向同一個區(qū)域(常量池)靠抑,然后String有一個基本特性是它的不可變性量九,如果改變就新增,這樣的話雖然是淺拷貝颂碧,但變相的實現(xiàn)了深拷貝的效果荠列。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市载城,隨后出現(xiàn)的幾起案子肌似,更是在濱河造成了極大的恐慌,老刑警劉巖诉瓦,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件川队,死亡現(xiàn)場離奇詭異,居然都是意外死亡睬澡,警方通過查閱死者的電腦和手機固额,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來煞聪,“玉大人斗躏,你說我怎么就攤上這事∶兹疲” “怎么了瑟捣?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵馋艺,是天一觀的道長栅干。 經(jīng)常有香客問我,道長捐祠,這世上最難降的妖魔是什么碱鳞? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮踱蛀,結(jié)果婚禮上窿给,老公的妹妹穿的比我還像新娘贵白。我一直安慰自己,他們只是感情好崩泡,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布禁荒。 她就那樣靜靜地躺著,像睡著了一般角撞。 火紅的嫁衣襯著肌膚如雪呛伴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天谒所,我揣著相機與錄音热康,去河邊找鬼。 笑死劣领,一個胖子當(dāng)著我的面吹牛姐军,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播尖淘,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼奕锌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了村生?” 一聲冷哼從身側(cè)響起歇攻,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎梆造,沒想到半個月后缴守,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡镇辉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年屡穗,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忽肛。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡村砂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出屹逛,到底是詐尸還是另有隱情础废,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布罕模,位于F島的核電站评腺,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏淑掌。R本人自食惡果不足惜蒿讥,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧芋绸,春花似錦媒殉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至马昙,卻和暖如春苦酱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背给猾。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工疫萤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人敢伸。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓扯饶,卻偏偏與公主長得像,于是被迫代替她去往敵國和親池颈。 傳聞我的和親對象是個殘疾皇子尾序,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Java8張圖 11、字符串不變性 12躯砰、equals()方法每币、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,707評論 0 11
  • Java中的equals方法和hashCode方法是Object中的琢歇,所以每個對象都是有這兩個方法的兰怠,有時候我們需...
    差不多先生_tl閱讀 1,369評論 2 6
  • “有狐綏綏,在彼其梁李茫!”這是方遠(yuǎn)第一次看見綏綏時腦海中閃現(xiàn)出的詞揭保。 沒錯,當(dāng)時聽到這個名字的時候...
    方一落閱讀 262評論 0 1
  • 各位家長: 望子成龍、望女成鳳宠互,一定是您最殷切期望!可是味榛,如何讓孩子成龍、成鳳予跌,這也許是困攏每個家長的一道...
    徐鼎文閱讀 325評論 0 0
  • 如果我很喜歡一個男生,他也愿意接受我做女朋友汁掠,但他心里裝著一個別的女生略吨,我還愿意和他在一起嗎? 關(guān)...
    李嚕嚕小姐閱讀 1,132評論 0 4