نادیده گرفتن متدهای برابر () و hashCode() در جاوا

Equalsو hashCodeمتدهای اساسی هستند که در کلاس اعلام شده Objectو در کتابخانه های استاندارد جاوا موجود هستند. بارگذاری بیش از حد متدهای برابر () و hashCode() در جاوا - 1این روش еquals()برای مقایسه اشیاء و hashCodeتولید یک کد عدد صحیح برای شی مورد استفاده قرار می گیرد. این روش ها به طور گسترده در کتابخانه های استاندارد جاوا هنگام درج و بازیابی اشیاء در HashMap. این روش equalهمچنین برای اطمینان از اینکه فقط اشیاء منحصربه‌فرد در HashSetسایر Setپیاده‌سازی‌ها ذخیره می‌شوند، و همچنین در هر مورد دیگری که اشیاء نیاز به مقایسه دارند، استفاده می‌شود. پیاده‌سازی پیش‌فرض متد equals()در کلاس java.lang.Object، ارجاع‌ها را با آدرس‌های حافظه‌ای که متغیرها ذخیره می‌کنند مقایسه می‌کند و trueتنها در صورتی برمی‌گرداند که آدرس‌ها مطابقت داشته باشند، به عبارت دیگر، متغیرها به همان شی اشاره می‌کنند. اگر انتظار دارید که مقایسه بر اساس منطق طبیعی یا منطق تجاری انجام شود، جاوا توصیه می‌کند که روش‌ها equals()و را باطل کنید. hashCode()بسیاری از کلاس ها در کتابخانه های استاندارد جاوا آنها را باطل می کنند، به عنوان مثال کلاس Stringلغو می شود equalsبه طوری که trueاگر محتویات دو شی مورد مقایسه یکسان باشد، برمی گردد. کلاس wrapper Integerروش را equalبرای انجام مقایسه عددی نادیده می گیرد و غیره. از آنجایی که جاوا برای مقایسه آنها و به متدهایی HashMapنیز متکی است ، جاوا قوانین زیر را برای نادیده گرفتن این روش ها ارائه می دهد: HashTableequals()hashCode()keyvalues
  1. انعکاس پذیری: جسم باید با خودش برابر باشد.
  2. متقارن: اگر a.equals(b)برمی گردد true، پس b.equals(a)باید نیز برگردد true.
  3. Transitivity: اگر a.equals(b)برمی گردد trueو b.equals(c)همچنین برمی گردد true، پس c.equals(a)باید نیز برگردد true.
  4. سازگاری: فراخوانی های مکرر به یک متد equals()باید همان مقدار را برگردانند تا زمانی که برخی از مقادیر ویژگی شی تغییر نکرده باشند. یعنی اگر دو شی در جاوا با هم برابر باشند، تا زمانی که خصوصیات آنها بدون تغییر باقی بماند، برابر خواهند بود.
  5. مقایسه null: شی باید بررسی شود null. اگر شی برابر باشد null، متد باید برگردد false، نه NullPointerException. مثلاً a.equals(null)باید برگردد false.

توافق بین برابر و هش کد در جاوا

  1. اگر اشیاء در نتایج اجرای متد برابر باشند equals، hashcodeباید یکسان باشند.
  2. اگر اشیاء در نتایج اجرای متد برابر نباشند equals، hashcodeمی توانند یکسان یا متفاوت باشند. با این حال، برای بهبود عملکرد، بهتر است که اشیاء مختلف کدهای متفاوتی را برگردانند.

نحوه نادیده گرفتن متد برابر در جاوا

  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()، اما StringBufferoverride نمی کند.

  5. در صورت امکان، فیلدهایی را immutableبا استفاده از finalمتغیرهای جاوا ایجاد کنید.

  6. هنگام مقایسه Stringاشیا، equals()به جای آن از عملگر . استفاده کنید ==.

  7. دو شی که از نظر منطقی با هم برابر هستند اما از اشیاء مختلف بارگیری می شوند ClassLoaderنمی توانند برابر باشند. به یاد داشته باشید که اگر کلاس لودر متفاوت باشد، بررسی با getClass()باز خواهد گشت .false

  8. @Overrideاز حاشیه نویسی در روش . نیز استفاده کنید hashCode، زیرا از خطاهای ظریفی مانند مقدار بازگشتی جلوگیری می intکند long.

PS همکاران عزیز! من این مقاله را در حل مسائل سطح 21 مفید یافتم! برای شما در تحلیل این موضوع آرزوی موفقیت دارم، از ترجمه استفاده کنید! امیدوارم به من کمک کنید تا رتبه ام را بالا ببرم، زیرا در حال حاضر حتی نمی توانم در این انجمن نظر بگذارم. با تشکر فراوان، همه! مقاله اصلی به دلیل کمبود وقت، نکاتی را حذف کردم، اما هر آنچه که برای حل مسائل سطح 21 باید بدانید را ترجمه کردم.