JavaRush /จาวาบล็อก /Random-TH /วิธีการโอเวอร์โหลดเท่ากับ () และ hashCode () ใน Java
Coder
ระดับ

วิธีการโอเวอร์โหลดเท่ากับ () และ hashCode () ใน Java

เผยแพร่ในกลุ่ม

การเอาชนะวิธีการเท่ากับ () และ hashCode () ใน Java

EqualsและhashCodeเป็นวิธีการพื้นฐานที่ประกาศในคลาสObjectและมีอยู่ในไลบรารี Java มาตรฐาน วิธีการโอเวอร์โหลดเท่ากับ () และ hashCode () ใน Java - 1วิธีการนี้еquals()ใช้ในการเปรียบเทียบวัตถุและhashCodeสร้างรหัสจำนวนเต็มสำหรับวัตถุ วิธีการเหล่านี้ใช้กันอย่างแพร่หลายในไลบรารีมาตรฐาน Java เมื่อแทรกและดึงอ็อบเจ็กต์ในHashMap. วิธีการนี้equalยังใช้เพื่อให้แน่ใจว่ามีการจัดเก็บเฉพาะอ็อบเจ็กต์ที่ไม่ซ้ำกันใน การใช้งาน HashSetอื่นๆSetรวมถึงในกรณีอื่นๆ ที่จำเป็นต้องเปรียบเทียบอ็อบเจ็กต์ การใช้งานเริ่มต้นของวิธีการequals()ในคลาสjava.lang.Objectจะเปรียบเทียบการอ้างอิงไปยังที่อยู่หน่วยความจำที่ตัวแปรจัดเก็บและส่งกลับtrueเฉพาะในกรณีที่ที่อยู่ตรงกัน กล่าวคือ ตัวแปรอ้างอิงถึงวัตถุเดียวกัน Java แนะนำให้แทนที่ วิธีการ equals()และhashCode()หากคุณคาดว่าการเปรียบเทียบจะดำเนินการตามตรรกะทางธรรมชาติหรือตรรกะทางธุรกิจ คลาสจำนวนมากในไลบรารี Java มาตรฐานจะแทนที่คลาสเหล่านั้น เช่น คลาสStringจะแทนที่equalsเพื่อที่จะส่งคืนtrueหากเนื้อหาของทั้งสองอ็อบเจ็กต์ที่ถูกเปรียบเทียบเหมือนกัน คลาส wrapper จะแทนที่ Integerวิธีequalการดำเนินการเปรียบเทียบเชิงตัวเลข และอื่นๆ เนื่องจากJava HashMapยัง อาศัย และ วิธีการ ในการเปรียบเทียบและJava จึงเสนอกฎต่อไปนี้สำหรับการแทนที่วิธีการเหล่านี้: HashTableequals()hashCode()keyvalues
  1. การสะท้อนกลับ: วัตถุจะต้องเท่ากับตัวมันเอง
  2. สมมาตร: หากa.equals(b)ส่งคืนtrueก็b.equals(a)จะต้องส่งคืนtrueด้วย
  3. การผ่านผ่าน: ถ้าa.equals(b)มันส่งคืนtrueและb.equals(c)ส่งคืนด้วยtrueจะc.equals(a)ต้องส่งคืนtrueด้วย
  4. ความสอดคล้อง: การเรียกเมธอดซ้ำๆequals()จะต้องส่งคืนค่าเดียวกันตราบใดที่ค่าคุณสมบัติของออบเจ็กต์บางส่วนไม่เปลี่ยนแปลง นั่นคือหากวัตถุสองชิ้นเท่ากันใน Java วัตถุทั้งสองจะเท่ากันตราบใดที่คุณสมบัติของวัตถุยังคงไม่เปลี่ยนแปลง
  5. การเปรียบเทียบnull: วัตถุจะต้องได้รับการตรวจnullสอบ หากวัตถุมีค่าเท่ากับnullวิธีการก็ควรส่งคืนfalseไม่ใช่ NullPointerExceptionตัวอย่างเช่นa.equals(null)ควรส่งfalseคืน

ข้อตกลงระหว่างเท่ากับและ hashCode ใน Java

  1. หากวัตถุมีค่าเท่ากันในผลลัพธ์ของการดำเนินการเมธอด วัตถุequalsนั้นhashcodeจะต้องเหมือนกัน
  2. หากออบเจ็กต์ไม่เท่ากันในผลลัพธ์ของการดำเนินการเมธอดequalsก็hashcodeสามารถเหมือนกันหรือต่างกันก็ได้ อย่างไรก็ตาม เพื่อปรับปรุงประสิทธิภาพ ควรให้อ็อบเจ็กต์ที่แตกต่างกันส่งคืนโค้ดที่แตกต่างกันจะดีกว่า

วิธีแทนที่วิธีเท่ากับใน Java

  1. @Override
    public boolean equals(Object obj) {
    /*1. Check*/if (obj == this) {
    /*and return */ return true;
             }
  2. Проверьте an object на null, а также проверьте, чтобы an objectы были одного типа. Не делайте проверку с помощью instanceof так How такая проверка будет возвращать true для подклассов и будет работать правильно только в случае если ваш класс объявлен How immutable. Вместо этого можно использовать getClass();

    if (obj == null || obj.getClass() != this.getClass()) {
                return false;
    }
  3. Объявите переменную типа, который вы сравниваете, и приведите obj к этому типу. Потом сравнивайте каждый атрибут типа начиная с численных атрибутов (если имеются) потому что численные атрибуты проверяются быстрей. Сравнивайте атрибуты с помощью операторов И и ИЛИ (так называемые short-circuit logical operators) для объединения проверок с другими атрибутами.

    Person guest = (Person) obj;
            return id == guest.id && (firstName == guest.firstName ||
                (firstName != null && firstName.equals(guest.getFirstName())))
                    && (lastName == guest.lastName || (lastName != null &&                      lastName .equals(guest.getLastName())));
    }
Полный пример переопределения метода equals в Java
/** * Person class with equals and hashcode implementation in Java * @author Javin Paul */
public class Person {
    private int id;
    private String firstName;
    private String lastName;

    public int getId() { return id; }
    public void setId(int id) { this.id = id;}

    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }
    @Override
    public boolean equals(Object obj) {
    if (obj == this) {
        return true;
    }
    if (obj == null || obj.getClass() != this.getClass()) {
        return false;
    }

    Person guest = (Person) obj;
    return id == guest.id
        && (firstName == guest.firstName
            || (firstName != null &&firstName.equals(guest.getFirstName())))        && (lastName == guest.lastName
            || (lastName != null && lastName .equals(guest.getLastName())
            ));
    }
    @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());             result = prime * result + id; result = prime * result +
        ((lastName == null) ? 0 : lastName.hashCode()); return result;
    }
 }

Распространенные ошибки при переопределении equals в Java

  1. Вместо того, чтобы переопределять метод equals (Override) программист перегружает его (Overload)Синтаксис метода equals() в классе Object определен How public boolean equals(Object obj), но многие программисты ненароком перегружают метод: public boolean equals(Person obj) - instead of Object в качестве аргумента используют Name своего класса (напр. Person). Эту ошибку сложно обнаружить из-за static binding. Таким образом, если вы вызовете этот метод для an object своего класса, то метод не просто скомпorруется, а даже сделает это корректно. Однако, если вы положите ваш an object в коллекцию, например ArrayList и вызовете метод contains(), работа которого основана на методе equals(), то метод contains не сможет обнаружить ваш an object.

  2. При переопределении метода equals() не проверять на null переменные, что в конечном итоге заканчивается NullPointerException при вызове equals(). Ниже представлен корректный code.

    firstname == guest.firstname || (firstname != null &&
         firstname.equals(guest.firstname));
  3. Третья распространенная ошибка это не переопределять метод hashCode(), а только equals(). Вы обязаны переопределять оба метода equals() и hashCode() в Java. Метод hashCode используется в hash -коллекциях(например HashSet), и чем меньше будет коллизий (одинаковый code при разных an objectх) тем эффективнее эти коллекции будут работать с an objectми вашего класса.

  4. Последняя распространенная ошибка программистов в том, что при переопределении метода equals() не сохраняется соответствие между методами equals() и compareTo(), что является неформальным требованием для избежания хранения дубликатов в Set (SortedSet, TreeSet).

Подсказки How писать в Java метод equals

  1. Большинство IDE такие How NetBeans, Eclipse и IntelliJ IDEA обеспечивают поддержку генерации методов equals() и hashCode(). В Eclipse нажмите правую кнопку -> source -> generate equals() и hashCode().

  2. Если в классе есть уникальный бизнес-ключ, то будет достаточно сделать проверку только на equalsство этих полей. Как в нашем примере “id” - уникальный номер для каждого Person.

  3. При переопределении hashCode() в Java удостоверьтесь в использовании всех полей, что были использованы в методе equals().

  4. Stringและคลาส wrapper เช่นIntegerและFloatแทนที่Doubleเมธอดequals()แต่StringBufferไม่ได้แทนที่

  5. เมื่อใดก็ตามที่เป็นไปได้ ให้สร้างฟิลด์immutableโดยใช้finalตัวแปรใน Java

  6. เมื่อเปรียบเทียบStringวัตถุ ให้ใช้equals(). โอเปอเรเตอร์==แทน

  7. วัตถุสองชิ้นที่มีความเท่าเทียมกันทางตรรกะ แต่โหลดจากวัตถุที่แตกต่างกันClassLoaderไม่สามารถเท่ากันได้ โปรดจำไว้ว่าการตรวจสอบด้วยgetClass()จะกลับมาfalseหากคลาสตัวโหลดแตกต่างออกไป

  8. ใช้@Overrideคำอธิบายประกอบในเมธอด . hashCodeเนื่องจากจะป้องกันข้อผิดพลาดเล็กๆ น้อยๆ เช่น ค่าที่ส่งคืนของint. อย่างไรก็ตาม โปรแกรมเมอร์บางคนส่งlongคืน

ป.ล. เรียนเพื่อนร่วมงาน! ฉันพบว่าบทความนี้มีประโยชน์ในการแก้ปัญหาระดับ 21! ฉันขอให้คุณโชคดีในการวิเคราะห์หัวข้อนี้ ใช้การแปล! ฉันหวังว่าคุณจะช่วยฉันเพิ่มคะแนน เนื่องจากตอนนี้ฉันไม่สามารถแสดงความคิดเห็นในฟอรัมนี้ได้ ขอบคุณมากทุกคน! บทความต้นฉบับ ฉันละเว้นบางประเด็นเนื่องจากขาดเวลาว่าง แต่ฉันแปลทุกสิ่งที่คุณจำเป็นต้องรู้เพื่อแก้ไขปัญหาระดับ 21
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION