.equals และ .hashCode เริ่มต้นจะทำงานกับชั้นเรียนของฉันได้อย่างไร


106

สมมติว่าฉันมีชั้นเรียนของตัวเอง

public class MyObj { /* ... */ }

มีคุณลักษณะและวิธีการบางอย่าง ไม่ใช้งานเท่ากับไม่ใช้ hashCode

เมื่อเราเรียกเท่ากับและ hashCode แล้วการใช้งานเริ่มต้นคืออะไร? จากคลาส Object? แล้วพวกมันคืออะไร? ค่าเริ่มต้นเท่ากับจะทำงานอย่างไร? hashCode เริ่มต้นจะทำงานอย่างไรและอะไรจะกลับมา? == จะตรวจสอบว่าพวกเขาอ้างอิงถึงวัตถุเดียวกันหรือไม่ดังนั้นจึงเป็นเรื่องง่าย แต่วิธีการเท่ากับ () และ hashCode () ล่ะ?

คำตอบ:


94

ใช่การใช้งานเริ่มต้นคือ Object (โดยทั่วไปพูดคือถ้าคุณสืบทอดจากคลาสที่กำหนดใหม่เท่ากับและ / หรือ hashCode คุณจะใช้การใช้งานนั้นแทน)

จากเอกสารประกอบ:

equals

วิธีการเท่ากับสำหรับคลาสอ็อบเจ็กต์ใช้ความสัมพันธ์ความเท่าเทียมที่เป็นไปได้ที่แยกแยะได้มากที่สุดกับอ็อบเจ็กต์ นั่นคือสำหรับค่าอ้างอิงที่ไม่ใช่ค่าว่าง x และ y วิธีนี้จะคืนค่าจริงถ้า x และ y อ้างถึงวัตถุเดียวกันเท่านั้น (x == y มีค่าเป็นจริง)

hashCode

เท่าที่ใช้งานได้จริงวิธี hashCode ที่กำหนดโดยคลาส Object จะส่งคืนจำนวนเต็มที่แตกต่างกันสำหรับอ็อบเจ็กต์ที่แตกต่างกัน (โดยทั่วไปจะนำไปใช้โดยการแปลงที่อยู่ภายในของวัตถุเป็นจำนวนเต็ม แต่เทคนิคการใช้งานนี้ไม่จำเป็นสำหรับภาษาโปรแกรม Java ™)


50

จากObjectหนึ่งในการใช้งาน JVM:

public boolean equals(Object object) {
    return this == object;
}

public int hashCode() {
    return VMMemoryManager.getIdentityHashCode(this);
}

ในทั้งสองกรณีเป็นเพียงการเปรียบเทียบที่อยู่หน่วยความจำของวัตถุที่เป็นปัญหา


7
JDK มันมาจากรุ่นไหน? ในv6u23 ea:public native int hashCode();
khachik

@kha - คุณพูดถูกฉันคิดว่าฉันติดตามการใช้งานเนทีฟอย่างหนึ่งเพื่อดูว่ามันทำอะไรได้จริง
Brad Mace

10

มีการใช้งานเริ่มต้นของequals()และhashCode()ใน Object หากคุณไม่ได้จัดเตรียมการใช้งานของคุณเองระบบจะใช้สิ่งเหล่านี้ สำหรับequals()สิ่งนี้หมายถึงการ==เปรียบเทียบ: วัตถุจะเท่ากันก็ต่อเมื่อเป็นวัตถุเดียวกันเท่านั้น สำหรับhashCode()การJavadocมีคำอธิบายที่ดี

สำหรับข้อมูลเพิ่มเติมโปรดดู Effective Java บทที่ 3 (pdf) ข้อ 8


1

ใช่จากObjectคลาสเนื่องจากคลาสของคุณขยาย Object โดยปริยาย เพียงแค่ผลตอบแทนequals การใช้งานเป็นแบบเนทีฟ เพียงแค่การคาดเดา - มันจะส่งกลับตัวชี้ไปที่วัตถุthis == objhashCode


2
เป็นตัวชี้ไปยังวัตถุที่อยู่ในหน่วยความจำ แต่ไม่ใช่ที่อยู่หน่วยความจำของวัตถุ GC สามารถย้ายวัตถุไปรอบ ๆ ในหน่วยความจำและรหัสแฮชจะยังคงเหมือนเดิม
Jeremy

@Jeremy ขอบคุณ stackoverflow.com/questions/2427631/…อาจจะน่าสนใจ
khachik

1

หากคุณไม่ได้จัดเตรียมการนำไปใช้งานของคุณเองระบบจะใช้หนึ่งที่ได้มาจาก Object ไม่เป็นไรเว้นแต่คุณจะวางแผนที่จะใส่อินสแตนซ์คลาสของคุณลงในเช่น HashSet (คอลเล็กชันใด ๆ ที่ใช้ hashCode ()) หรือสิ่งที่ต้องการตรวจสอบความเท่าเทียมกันของวัตถุ (เช่น HashSet มีวิธีการ ()) มิฉะนั้นจะทำงานผิดพลาดหากนั่นคือสิ่งที่คุณขอ

มันเป็นเรื่องง่ายมากที่จะให้การดำเนินการของตัวเองของวิธีการเหล่านี้ต้องขอบคุณHashCodeBuilderและEqualsBuilderจากApache คอมมอนส์แลง


(ก) เหตุใดคุณจึงกล่าวว่า 'การใช้งานเริ่มต้นของ' เท่ากับ 'คลาส Object จะทำงานกับ HashSet ไม่ถูกต้อง ซึ่งขัดแย้งกับคำตอบอื่น ๆ ในหน้านี้ (b) ขอบคุณสำหรับลิงก์ Commons Lang
Basil Bourque

1
@ บาซิล: ฉันไม่คิดว่ามันขัดแย้งกัน แน่นอนว่าการใช้งานเริ่มต้นจะใช้งานได้ ... แต่ไม่ใช่อย่างที่คุณคาดหวัง นั่นคือเนื่องจาก equals () ใช้ความเท่าเทียมกันในการอ้างอิงวัตถุที่เหมือนกันสองชิ้นจะ "ต่างกัน" ในสายตาของการใช้งานเริ่มต้น ด้วยเหตุนี้คุณอาจมีสองอินสแตนซ์ที่เหมือนกันในชุดของคุณ และโดยทั่วไปแล้วการใช้ชุดคือเมื่อคุณต้องการกำจัดรายการที่ซ้ำกัน ...
Paweł Dyda

@ PawełDyda: โดยทั่วไปพฤติกรรมเริ่มต้นจะถูกต้องสำหรับประเภทที่เปลี่ยนแปลงได้ หากFooและBarเป็นการอ้างอิงถึงสองอินสแตนซ์ที่แตกต่างกันของชนิดที่เปลี่ยนแปลงได้และมีวิธีการ (เช่นSomeMutatingMethod) ที่Foo.SomeMutatingMethod()ไม่ส่งผลกระทบBarในลักษณะเดียวกันFooความแตกต่างนั้นควรเพียงพอที่จะถือว่าวัตถุนั้นไม่เท่ากัน
supercat

0

Developerworksของ IBM กล่าวว่า:

ภายใต้การใช้งานเริ่มต้นนี้การอ้างอิงสองรายการจะเท่ากันก็ต่อเมื่ออ้างอิงถึงวัตถุเดียวกันเท่านั้น ในทำนองเดียวกันการนำค่าเริ่มต้นของ hashCode () มาใช้โดย Object นั้นได้มาจากการแมปที่อยู่หน่วยความจำของอ็อบเจ็กต์กับค่าจำนวนเต็ม

อย่างไรก็ตามเพื่อให้แน่ใจในรายละเอียดการใช้งานที่ถูกต้องสำหรับเวอร์ชัน Java ของผู้จำหน่ายรายใดรายหนึ่งควรมองว่าเป็นแหล่งที่มา (หากมี)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.