CodeGym /จาวาบล็อก /สุ่ม /วิธีเท่ากับและ hashCode: แนวทางปฏิบัติที่ดีที่สุด
John Squirrels
ระดับ
San Francisco

วิธีเท่ากับและ hashCode: แนวทางปฏิบัติที่ดีที่สุด

เผยแพร่ในกลุ่ม
สวัสดี! วันนี้เราจะพูดถึงสองวิธีที่สำคัญใน Java: equals()และhashCode(). นี่ไม่ใช่ครั้งแรกที่เราพบพวกเขา: หลักสูตร CodeGym เริ่มต้นด้วยบทเรียนสั้นๆเกี่ยวกับequals()— โปรดอ่านหากคุณลืมหรือไม่เคยเห็นมาก่อน... วิธีเท่ากับและ hashCode: แนวทางปฏิบัติที่ดีที่สุด - 1ในบทเรียนวันนี้ เราจะพูดถึง แนวคิดเหล่านี้โดยละเอียด และเชื่อฉัน เรามีเรื่องต้องคุยกัน! แต่ก่อนที่เราจะไปยังสิ่งใหม่ เรามารีเฟรชสิ่งที่เราได้พูดถึงไปแล้ว :) อย่างที่คุณจำได้ โดยปกติแล้วเป็นความคิดที่ดีที่จะเปรียบเทียบวัตถุสองชิ้นโดยใช้ตัวดำเนินการ==เพราะ==เปรียบเทียบการอ้างอิง นี่คือตัวอย่างของเราเกี่ยวกับรถยนต์จากบทเรียนล่าสุด:

public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

       Car car1 = new Car();
       car1.model = "Ferrari";
       car1.maxSpeed = 300;

       Car car2 = new Car();
       car2.model = "Ferrari";
       car2.maxSpeed = 300;

       System.out.println(car1 == car2);
   }
}
เอาต์พุตคอนโซล:

false
ดูเหมือนว่าเราได้สร้างCarวัตถุสองชิ้นที่เหมือนกัน: ค่าของฟิลด์ที่สอดคล้องกันของวัตถุรถยนต์สองชิ้นนั้นเหมือนกัน แต่ผลลัพธ์ของการเปรียบเทียบยังคงเป็นเท็จ เราทราบเหตุผลแล้ว: การ อ้างอิง car1และcar2ชี้ไปยังที่อยู่หน่วยความจำที่แตกต่างกัน ดังนั้นจึงไม่เท่ากัน แต่เรายังต้องการเปรียบเทียบวัตถุทั้งสอง ไม่ใช่การอ้างอิงสองรายการ ทางออกที่ดีที่สุดสำหรับการเปรียบเทียบวัตถุคือequals()วิธีการ

เท่ากับ () วิธีการ

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

public boolean equals(Object obj) {
   return (this == obj);
}
นี่คือวิธีการequals()กำหนดวิธีการในObjectชั้นเรียน นี่เป็นการเปรียบเทียบอ้างอิงอีกครั้งหนึ่ง ทำไมพวกเขาถึงทำแบบนั้น? แล้วผู้สร้างภาษารู้ได้อย่างไรว่าอ็อบเจกต์ใดในโปรแกรมของคุณถือว่าเท่ากันและออบเจกต์ใดไม่เท่ากัน :) นี่คือประเด็นหลักของequals()เมธอด — ผู้สร้างคลาสคือผู้กำหนดลักษณะที่จะใช้เมื่อตรวจสอบความเท่าเทียมกันของออบเจกต์ของคลาส จากนั้นคุณแทนที่equals()วิธีการในชั้นเรียนของคุณ หากคุณไม่ค่อยเข้าใจความหมายของ "กำหนดลักษณะใด" ลองพิจารณาตัวอย่าง นี่คือคลาสง่ายๆ ที่เป็นตัวแทนของผู้ชายMan:

public class Man {

   private String noseSize;
   private String eyesColor;
   private String haircut;
   private boolean scars;
   private int dnaCode;

public Man(String noseSize, String eyesColor, String haircut, boolean scars, int dnaCode) {
   this.noseSize = noseSize;
   this.eyesColor = eyesColor;
   this.haircut = haircut;
   this.scars = scars;
   this.dnaCode = dnaCode;
}

   // Getters, setters, etc.
}
สมมติว่าเรากำลังเขียนโปรแกรมที่ต้องการตัดสินว่าคนสองคนเป็นฝาแฝดที่เหมือนกันหรือแค่หน้าตาเหมือนกัน เรามีลักษณะห้าประการ: ขนาดจมูก สีตา ทรงผม การมีแผลเป็น และผลการตรวจดีเอ็นเอ (เพื่อความง่าย เราจะแทนค่านี้เป็นรหัสจำนวนเต็ม) คุณคิดว่าลักษณะใดต่อไปนี้ที่ทำให้โปรแกรมของเราสามารถระบุฝาแฝดที่เหมือนกันได้ วิธีเท่ากับและ hashCode: แนวทางปฏิบัติที่ดีที่สุด - 2แน่นอน การตรวจดีเอ็นเอเท่านั้นที่สามารถรับประกันได้ คนสองคนสามารถมีสีตา ทรงผม จมูก และแม้แต่รอยแผลเป็นที่เหมือนกันได้ มีคนจำนวนมากในโลกนี้ และเป็นไปไม่ได้ที่จะรับประกันว่าจะไม่มีเนื้อคู่คนใดในโลกนี้ แต่เราต้องการกลไกที่เชื่อถือได้: เฉพาะผลการตรวจดีเอ็นเอเท่านั้นที่จะทำให้เราได้ข้อสรุปที่ถูกต้อง สิ่งนี้หมายความว่าอย่างไรสำหรับequals()วิธีการ ของเรา เราต้องแทนที่มันในManชั้นเรียนโดยคำนึงถึงข้อกำหนดของโปรแกรมของเรา วิธีการควรเปรียบเทียบint dnaCodeฟิลด์ของวัตถุทั้งสอง ถ้าเท่ากัน วัตถุก็เท่ากัน

@Override
public boolean equals(Object o) {
   Man man = (Man) o;
   return dnaCode == man.dnaCode;
}
มันง่ายขนาดนั้นเลยเหรอ? ไม่เชิง. เรามองข้ามบางสิ่งไป สำหรับอ็อบเจ็กต์ของเรา เราระบุเพียงฟิลด์เดียวที่เกี่ยวข้องกับการสร้างความเท่าเทียมกันของอ็อบเจ็กต์dnaCode: ลองจินตนาการว่าเราไม่มี 1 แต่มี 50 ฟิลด์ที่เกี่ยวข้อง และถ้าทั้ง 50 ฟิลด์ของวัตถุทั้งสองมีค่าเท่ากัน วัตถุนั้นจะเท่ากัน สถานการณ์ดังกล่าวก็เป็นไปได้เช่นกัน ปัญหาหลักคือการสร้างความเท่าเทียมกันโดยการเปรียบเทียบ 50 ฟิลด์เป็นกระบวนการที่ใช้เวลานานและใช้ทรัพยากรมาก ลองจินตนาการว่านอกเหนือจากคลาสของเราแล้วManเรายังมีWomanคลาสที่มีฟิลด์เดียวกันกับที่มีอยู่ใน Manถ้าโปรแกรมเมอร์คนอื่นใช้คลาสของเรา เขาหรือเธอสามารถเขียนโค้ดได้ง่ายๆ ดังนี้:

public static void main(String[] args) {
  
   Man man = new Man(........); // A bunch of parameters in the constructor

   Woman woman = new Woman(.........); // The same bunch of parameters.

   System.out.println(man.equals(woman));
}
ในกรณีนี้ การตรวจสอบค่าของฟิลด์นั้นไม่มีจุดหมาย: เราสามารถเห็นได้ทันทีว่าเรามีออบเจกต์ของสองคลาสที่แตกต่างกัน ดังนั้นจึงไม่มีทางที่พวกมันจะเท่ากันได้! ซึ่งหมายความว่าเราควรเพิ่มการตรวจสอบequals()วิธีการเปรียบเทียบคลาสของวัตถุที่เปรียบเทียบ เป็นเรื่องดีที่เราคิดอย่างนั้น!

@Override
public boolean equals(Object o) {
   if (getClass() != o.getClass()) return false;
   Man man = (Man) o;
   return dnaCode == man.dnaCode;
}
แต่บางทีเราอาจลืมอะไรไปหรือเปล่า? อืม... อย่างน้อยที่สุด เราควรตรวจสอบว่าเราไม่ได้เปรียบเทียบวัตถุกับตัวมันเอง! หากการอ้างอิง A และ B ชี้ไปที่ที่อยู่หน่วยความจำเดียวกัน แสดงว่าเป็นวัตถุเดียวกัน และเราไม่ต้องเสียเวลาเปรียบเทียบ 50 ฟิลด์

@Override
public boolean equals(Object o) {
   if (this == o) return true;
   if (getClass() != o.getClass()) return false;
   Man man = (Man) o;
   return dnaCode == man.dnaCode;
}
nullการเพิ่มเครื่องหมายถูกสำหรับ : ไม่มีวัตถุใดสามารถเท่ากับได้ก็nullไม่ เสียหาย ดังนั้น หากพารามิเตอร์เมธอดเป็นโมฆะ แสดงว่าไม่มีประเด็นในการตรวจสอบเพิ่มเติม เมื่อคำนึงถึงสิ่งนี้แล้วequals()วิธีการของเราสำหรับManชั้นเรียนจะเป็นดังนี้:

@Override
public boolean equals(Object o) {
   if (this == o) return true;
   if (o == null || getClass() != o.getClass()) return false;
   Man man = (Man) o;
   return dnaCode == man.dnaCode;
}
เราทำการตรวจสอบเบื้องต้นทั้งหมดตามที่กล่าวไว้ข้างต้น ในตอนท้ายของวัน หาก:
  • เรากำลังเปรียบเทียบวัตถุสองชิ้นในคลาสเดียวกัน
  • และวัตถุที่นำมาเปรียบเทียบก็ไม่ใช่วัตถุเดียวกัน
  • และวัตถุที่ผ่านไม่ได้null
...จากนั้นเราจะดำเนินการเปรียบเทียบลักษณะที่เกี่ยวข้องกัน สำหรับเรา นี่หมายถึงdnaCodeฟิลด์ของวัตถุทั้งสอง เมื่อแทนที่equals()เมธอด อย่าลืมปฏิบัติตามข้อกำหนดเหล่านี้:
  1. การสะท้อนแสง

    เมื่อequals()เมธอดถูกใช้เพื่อเปรียบเทียบวัตถุใด ๆ กับตัวเอง มันจะต้องคืนค่าจริง
    เราได้ปฏิบัติตามข้อกำหนดนี้แล้ว วิธีการของเราประกอบด้วย:

    
    if (this == o) return true;
    

  2. สมมาตร.

    ถ้าa.equals(b) == trueอย่างนั้นก็b.equals(a)ต้องกลับ วิธีการของเราเป็นไปตามข้อกำหนดนี้เช่นกันtrue

  3. การเปลี่ยนแปลง

    หากวัตถุสองชิ้นมีค่าเท่ากับวัตถุที่สาม วัตถุทั้งสองจะต้องเท่ากัน
    ถ้าa.equals(b) == trueและa.equals(c) == trueจะb.equals(c)ต้องคืนค่าจริงด้วย

  4. วิริยะ.

    ผลลัพธ์ของequals()ต้องเปลี่ยนเฉพาะเมื่อฟิลด์ที่เกี่ยวข้องมีการเปลี่ยนแปลง หากข้อมูลของวัตถุทั้งสองไม่เปลี่ยนแปลง ดังนั้นผลลัพธ์ของequals()จะต้องเหมือนกันเสมอ

  5. อสมการกับnull.

    สำหรับอ็อบเจกต์ใด ๆa.equals(null)ต้องส่งคืนค่าเท็จ
    นี่ไม่ใช่แค่ชุดของ "คำแนะนำที่เป็นประโยชน์" แต่เป็นสัญญาที่เข้มงวดซึ่งกำหนดไว้ในเอกสารประกอบของ Oracle

วิธีการ hashCode()

ตอนนี้เรามาพูดถึงhashCode()วิธีการ ทำไมถึงจำเป็น? เพื่อจุดประสงค์เดียวกันทุกประการ — เพื่อเปรียบเทียบวัตถุ แต่เรามีแล้วequals()! ทำไมต้องใช้วิธีอื่น? คำตอบนั้นง่าย: เพื่อปรับปรุงประสิทธิภาพ ฟังก์ชันแฮชซึ่งแสดงในภาษาจาวาโดยใช้hashCode()เมธอด จะส่งคืนค่าตัวเลขที่มีความยาวคงที่สำหรับออบเจกต์ใดๆ ใน Java hashCode()เมธอดจะส่งคืนตัวเลข 32 บิต ( int) สำหรับวัตถุใดๆ การเปรียบเทียบตัวเลขสองตัวนั้นเร็วกว่าการเปรียบเทียบวัตถุสองตัวโดยใช้equals()เมธอด โดยเฉพาะอย่างยิ่งหากเมธอดนั้นพิจารณาหลายฟิลด์ ถ้าโปรแกรมของเราเปรียบเทียบอ็อบเจกต์ การทำเช่นนี้ทำได้ง่ายกว่ามากโดยใช้รหัสแฮช เฉพาะในกรณีที่วัตถุมีค่าเท่ากันตามhashCode()วิธีการเท่านั้น การเปรียบเทียบจะดำเนินต่อไปที่equals()วิธี. อย่างไรก็ตาม นี่คือวิธีการทำงานของโครงสร้างข้อมูลแบบแฮช ตัวอย่างเช่นHashMap! เมธอดhashCode()เช่นequals()เมธอด ถูกแทนที่โดยผู้พัฒนา และเช่นเดียวกับ วิธีการ equals()นี้hashCode()มีข้อกำหนดอย่างเป็นทางการระบุไว้ในเอกสารประกอบของ Oracle:
  1. ถ้าสองออบเจกต์มีค่าเท่ากัน (เช่นequals()เมธอดส่งคืนค่าจริง) ดังนั้นออบเจกต์เหล่านั้นต้องมีรหัสแฮชเดียวกัน

    มิฉะนั้นวิธีการของเราจะไร้ความหมาย ดังที่เรากล่าวไว้ข้างต้นhashCode()ควรตรวจสอบก่อนเพื่อปรับปรุงประสิทธิภาพ หากรหัสแฮชต่างกัน การตรวจสอบจะส่งกลับค่าเท็จ แม้ว่าออบเจกต์จะเท่ากันตามวิธีที่เรากำหนดเมธอดequals()ก็ตาม

  2. หากhashCode()มีการเรียกใช้เมธอดหลายครั้งบนออบเจกต์เดียวกัน เมธอดนั้นจะต้องส่งกลับหมายเลขเดิมทุกครั้ง

  3. กฎข้อที่ 1 ไม่ได้ทำงานในทิศทางตรงกันข้าม วัตถุสองชิ้นที่แตกต่างกันสามารถมีรหัสแฮชเดียวกันได้

กฎข้อที่สามค่อนข้างสับสน เป็นไปได้อย่างไร? คำอธิบายนั้นค่อนข้างง่าย เมธอดhashCode()จะคืนค่าไฟล์int. An intเป็นตัวเลข 32 บิต มีช่วงค่าที่จำกัด: ตั้งแต่ -2,147,483,648 ถึง +2,147,483,647 กล่าวอีกนัยหนึ่ง มีค่าที่เป็นไปได้มากกว่า 4 พันล้านค่าสำหรับไฟล์int. ลองจินตนาการว่าคุณกำลังสร้างโปรแกรมเพื่อจัดเก็บข้อมูลเกี่ยวกับผู้คนทั้งหมดที่อาศัยอยู่บนโลก แต่ละคนจะสอดคล้องกับวัตถุของตนเองPerson(คล้ายกับManชั้นเรียน) มีประมาณ 7.5 พันล้านคนที่อาศัยอยู่บนโลก กล่าวอีกนัยหนึ่ง ไม่ว่าเราจะเขียนอัลกอริทึมเพื่อการแปลงที่ชาญฉลาดเพียงใดPersonคัดค้าน int เรามีตัวเลขที่เป็นไปได้ไม่เพียงพอ เรามีค่า int ที่เป็นไปได้เพียง 4.5 พันล้านค่า แต่มีคนมากกว่านั้นอีกมาก ซึ่งหมายความว่าไม่ว่าเราจะพยายามมากแค่ไหน บางคนก็จะมีรหัสแฮชเหมือนกัน เมื่อสิ่งนี้เกิดขึ้น (รหัสแฮชตรงกันสำหรับสองวัตถุที่แตกต่างกัน) เราเรียกว่าการชนกัน เมื่อแทนที่เมธอดhashCode()หนึ่งในวัตถุประสงค์ของโปรแกรมเมอร์คือเพื่อลดจำนวนการชนที่อาจเกิดขึ้น การบัญชีสำหรับกฎเหล่านี้hashCode()วิธีการจะมีลักษณะอย่างไรในPersonชั้นเรียน แบบนี้:

@Override
public int hashCode() {
   return dnaCode;
}
น่าประหลาดใจ? :) หากคุณดูข้อกำหนด คุณจะเห็นว่าเราปฏิบัติตามข้อกำหนดทั้งหมด วัตถุที่equals()วิธีการของเราคืนค่าจริงก็จะเท่ากันhashCode()ตาม หากPersonวัตถุทั้งสองของเรามีค่าเท่ากันequals(นั่นคือ มีเหมือนกันdnaCode) วิธีการของเราจะคืนค่าเป็นจำนวนเดียวกัน ลองพิจารณาตัวอย่างที่ยากขึ้น สมมติว่าโปรแกรมของเราควรเลือกรถหรูสำหรับนักสะสมรถ การสะสมอาจเป็นงานอดิเรกที่ซับซ้อนและมีลักษณะเฉพาะหลายอย่าง รถปี 1963 คันหนึ่งมีราคาสูงกว่ารถปี 1964 ถึง 100 เท่า รถสีแดงปี 1970 มีราคาสูงกว่ารถสีน้ำเงินยี่ห้อเดียวกันในปีเดียวกันถึง 100 เท่า วิธีเท่ากับและ hashCode: แนวทางปฏิบัติที่ดีที่สุด - 4ในตัวอย่างก่อนหน้านี้ กับPersonคลาส เราละทิ้งฟิลด์ส่วนใหญ่ (เช่น ลักษณะของมนุษย์) ที่ไม่มีนัยสำคัญและใช้เฉพาะฟิลด์dnaCodeสนามในการเปรียบเทียบ ตอนนี้เรากำลังทำงานในอาณาจักรที่แปลกประหลาด ซึ่งไม่มีรายละเอียดเล็กน้อย! นี่คือLuxuryAutoชั้นเรียนของเรา:

public class LuxuryAuto {

   private String model;
   private int manufactureYear;
   private int dollarPrice;

   public LuxuryAuto(String model, int manufactureYear, int dollarPrice) {
       this.model = model;
       this.manufactureYear = manufactureYear;
       this.dollarPrice = dollarPrice;
   }

   // ...getters, setters, etc.
}
ตอนนี้เราต้องพิจารณาฟิลด์ทั้งหมดในการเปรียบเทียบของเรา ความผิดพลาดใดๆ ก็ตามอาจทำให้ลูกค้าเสียเงินหลายแสนดอลลาร์ ดังนั้น จะดีกว่าหากมีความปลอดภัยมากเกินไป:

@Override
public boolean equals(Object o) {
   if (this == o) return true;
   if (o == null || getClass() != o.getClass()) return false;

   LuxuryAuto that = (LuxuryAuto) o;

   if (manufactureYear != that.manufactureYear) return false;
   if (dollarPrice != that.dollarPrice) return false;
   return model.equals(that.model);
}
ในequals()วิธีการของเรา เรายังไม่ลืมการตรวจสอบทั้งหมดที่เราพูดถึงก่อนหน้านี้ แต่ตอนนี้เราเปรียบเทียบแต่ละฟิลด์ทั้งสามของวัตถุของเรา สำหรับโปรแกรมนี้ เราต้องการความเท่าเทียมกันอย่างแท้จริง กล่าวคือ ความเท่าเทียมกันของแต่ละฟิลด์ แล้วhashCode?

@Override
public int hashCode() {
   int result = model == null ? 0 : model.hashCode();
   result = result + manufactureYear;
   result = result + dollarPrice;
   return result;
}
ฟิลด์modelในชั้นเรียนของเราคือสตริง สิ่งนี้สะดวกเพราะStringคลาสแทนที่เมธอดhashCode()แล้ว เราคำนวณmodelรหัสแฮชของฟิลด์ จากนั้นเพิ่มผลรวมของฟิลด์ตัวเลขอีกสองฟิลด์เข้าไป นักพัฒนา Java มีเคล็ดลับง่ายๆ ที่พวกเขาใช้เพื่อลดจำนวนการชนกัน: เมื่อคำนวณรหัสแฮช ให้คูณผลลัพธ์ที่อยู่ตรงกลางด้วยจำนวนเฉพาะที่เป็นคี่ หมายเลขที่ใช้บ่อยที่สุดคือ 29 หรือ 31 เราจะไม่เจาะลึกรายละเอียดปลีกย่อยทางคณิตศาสตร์ในตอนนี้ แต่ในอนาคต โปรดจำไว้ว่าการคูณผลลัพธ์ระดับกลางด้วยจำนวนคี่ที่มากพอจะช่วย "กระจาย" ผลลัพธ์ของฟังก์ชันแฮช และ ดังนั้น ลดจำนวนวัตถุที่มีรหัสแฮชเดียวกัน สำหรับhashCode()วิธีการของเราใน LuxuryAuto จะมีลักษณะดังนี้:

@Override
public int hashCode() {
   int result = model == null ? 0 : model.hashCode();
   result = 31 * result + manufactureYear;
   result = 31 * result + dollarPrice;
   return result;
}
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับความซับซ้อนทั้งหมดของกลไกนี้ได้ในโพสต์นี้บน StackOverflowรวมถึงในหนังสือEffective Javaโดย Joshua Bloch ในที่สุดจุดสำคัญอีกจุดหนึ่งที่ควรค่าแก่การกล่าวถึง ทุกครั้งที่เราลบล้างเมธอดequals()and hashCode()เราเลือกฟิลด์อินสแตนซ์บางฟิลด์ที่นำมาพิจารณาในเมธอดเหล่านี้ เมธอดเหล่านี้พิจารณาฟิลด์เดียวกัน แต่เราสามารถพิจารณาฟิลด์ต่างๆ ในequals()​​และhashCode()? ในทางเทคนิคเราทำได้ แต่นี่เป็นความคิดที่ไม่ดี และนี่คือเหตุผล:

@Override
public boolean equals(Object o) {
   if (this == o) return true;
   if (o == null || getClass() != o.getClass()) return false;

   LuxuryAuto that = (LuxuryAuto) o;

   if (manufactureYear != that.manufactureYear) return false;
   return dollarPrice == that.dollarPrice;
}

@Override
public int hashCode() {
   int result = model == null ? 0 : model.hashCode();
   result = 31 * result + manufactureYear;
   result = 31 * result + dollarPrice;
   return result;
}
นี่คือวิธีการของเราequals()และhashCode()สำหรับLuxuryAutoชั้นเรียน วิธีhashCode()การยังคงไม่เปลี่ยนแปลง แต่เราลบmodelฟิลด์ออกจากequals()วิธีการ แบบจำลองไม่ใช่คุณลักษณะที่ใช้อีกต่อไปเมื่อequals()เมธอดเปรียบเทียบวัตถุสองชิ้น แต่เมื่อคำนวณรหัสแฮช ฟิลด์นั้นจะยังคงถูกนำมาพิจารณาด้วย เราได้อะไรจากผลลัพธ์? มาสร้างรถสองคันแล้วหาคำตอบกันเถอะ!

public class Main {

   public static void main(String[] args) {

       LuxuryAuto ferrariGTO = new LuxuryAuto("Ferrari 250 GTO", 1963, 70000000);
       LuxuryAuto ferrariSpider = new LuxuryAuto("Ferrari 335 S Spider Scaglietti", 1963, 70000000);

       System.out.println("Are these two objects equal to each other?");
       System.out.println(ferrariGTO.equals(ferrariSpider));

       System.out.println("What are their hash codes?");
       System.out.println(ferrariGTO.hashCode());
       System.out.println(ferrariSpider.hashCode());
   }
}

Are these two objects equal to each other? 
true 
What are their hash codes? 
-1372326051 
1668702472
ข้อผิดพลาด! ด้วยการใช้ฟิลด์ที่แตกต่างกันสำหรับequals()และhashCode()วิธีการ เราละเมิดสัญญาที่กำหนดไว้สำหรับพวกเขา! อ็อบเจกต์สองตัวที่เท่ากันตามequals()เมธอดต้องมีรหัสแฮชเดียวกัน เราได้รับคุณค่าที่แตกต่างกันสำหรับพวกเขา ข้อผิดพลาดดังกล่าวสามารถนำไปสู่ผลลัพธ์ที่เหลือเชื่ออย่างยิ่ง โดยเฉพาะอย่างยิ่งเมื่อทำงานกับคอลเลกชันที่ใช้แฮช ดังนั้น เมื่อคุณแทนที่equals()และhashCode()คุณควรพิจารณาฟิลด์เดียวกัน บทเรียนนี้ค่อนข้างยาว แต่คุณได้เรียนรู้มากมายในวันนี้! :) ตอนนี้ได้เวลากลับไปแก้งานแล้ว!
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION