JavaRush /Blog Java /Random-VI /Quá tải các phương thức bằng() và hashCode() trong Java
Coder
Mức độ

Quá tải các phương thức bằng() và hashCode() trong Java

Xuất bản trong nhóm

Ghi đè các phương thức bằng() và hashCode() trong Java

EqualshashCodelà các phương thức cơ bản được khai báo trong lớp Objectvà có trong các thư viện Java tiêu chuẩn. Nạp chồng phương thức Equals() và hashCode() trong Java - 1Phương thức này еquals()được sử dụng để so sánh các đối tượng và hashCodetạo mã số nguyên cho đối tượng. Các phương thức này được sử dụng rộng rãi trong các thư viện chuẩn Java khi chèn và truy xuất các đối tượng trong các tệp HashMap. Phương pháp này equalcũng được sử dụng để đảm bảo rằng chỉ các đối tượng duy nhất được lưu trữ trong các triển khai HashSetkhác Set, cũng như trong bất kỳ trường hợp nào khác mà các đối tượng cần được so sánh. Việc triển khai mặc định của phương thức equals()trong lớp java.lang.Objectso sánh các tham chiếu đến các địa chỉ bộ nhớ mà các biến lưu trữ và truechỉ trả về nếu các địa chỉ khớp nhau, nói cách khác, các biến tham chiếu đến cùng một đối tượng. Java khuyên bạn nên ghi đè các phương thức equals()and hashCode()nếu bạn muốn việc so sánh được thực hiện theo logic tự nhiên hoặc logic nghiệp vụ. Nhiều lớp trong thư viện Java tiêu chuẩn ghi đè lên chúng, ví dụ lớp Stringghi đè equalsđể nó trả về truenếu nội dung của hai đối tượng được so sánh giống nhau. Lớp trình bao bọc ghi đè Integerphương thức này equalđể thực hiện so sánh số, v.v. Vì Java HashMapcũng dựa vào các phương thức and để so sánh and , nên Java đưa ra các quy tắc sau để ghi đè các phương thức này: HashTableequals()hashCode()keyvalues
  1. Tính phản thân: Vật phải bằng chính nó.
  2. Đối xứng: nếu a.equals(b)nó trả về true, thì b.equals(a)nó cũng phải trả về true.
  3. Tính bắc cầu: nếu a.equals(b)nó trả về trueb.equals(c)cũng trả về true, thì c.equals(a)nó cũng phải trả về true.
  4. Tính nhất quán: Các lệnh gọi lặp lại đến một phương thức equals()phải trả về cùng một giá trị miễn là một số giá trị thuộc tính của đối tượng không bị thay đổi. Nghĩa là, nếu hai đối tượng bằng nhau trong Java thì chúng sẽ bằng nhau miễn là các thuộc tính của chúng không thay đổi.
  5. So sánh null: Đối tượng phải được kiểm tra null. Nếu đối tượng bằng null, thì phương thức sẽ trả về false, không phải NullPointerException. Ví dụ, a.equals(null)nó sẽ trả về false.

Thỏa thuận giữa bằng và hashCode trong Java

  1. Nếu các đối tượng bằng nhau về kết quả thực hiện phương thức equalsthì chúng hashcodephải giống nhau.
  2. Nếu các đối tượng không bằng nhau trong kết quả thực thi phương thức equalsthì chúng hashcodecó thể giống nhau hoặc khác nhau. Tuy nhiên, để cải thiện hiệu suất, tốt hơn là để các đối tượng khác nhau trả về các mã khác nhau.

Cách ghi đè phương thức bằng trong 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. Stringvà các lớp bao bọc như Integer, FloatDoubleghi đè phương thức equals()nhưng StringBufferkhông ghi đè.

  5. Bất cứ khi nào có thể, hãy tạo các trường immutablebằng cách sử dụng finalcác biến trong Java.

  6. Khi so sánh Stringcác đối tượng, equals()thay vào đó hãy sử dụng toán tử ==.

  7. Hai đối tượng có giá trị logic bằng nhau nhưng được tải từ các đối tượng khác nhau ClassLoaderthì không thể bằng nhau. Hãy nhớ rằng việc kiểm tra bằng getClass()sẽ trả về falsenếu lớp trình tải khác.

  8. Cũng sử dụng @Overridechú thích trên phương thức . hashCode, vì điều này ngăn ngừa các lỗi tinh vi như giá trị trả về của .Tuy intnhiên, một số lập trình viên trả về long.

Tái bút Các đồng nghiệp thân mến! Mình thấy bài viết này hữu ích trong việc giải các bài toán cấp 21! Chúc các bạn phân tích chủ đề này may mắn, sử dụng bản dịch nhé! Tôi hy vọng rằng bạn sẽ giúp tôi nâng cao xếp hạng của mình, vì bây giờ tôi thậm chí không thể để lại nhận xét trên diễn đàn này. Cảm ơn mọi người rất nhiều! Bài viết gốc tôi đã lược bỏ một số điểm do không có thời gian rảnh, nhưng tôi đã dịch mọi thứ bạn cần biết để giải quyết vấn đề cấp độ 21.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION