تجاوز أساليب يساوي () و hashCode () في جافا
Equals
وهي hashCode
الطرق الأساسية المعلنة في الفصل Object
والمضمنة في مكتبات Java القياسية. يتم استخدام الأسلوب еquals()
لمقارنة الكائنات وإنشاء hashCode
رمز عدد صحيح للكائن. تُستخدم هذه الأساليب على نطاق واسع في مكتبات Java القياسية عند إدراج الكائنات واسترجاعها في ملفات HashMap
. تُستخدم هذه الطريقة equal
أيضًا لضمان تخزين الكائنات الفريدة فقط في التطبيقات HashSet
الأخرى Set
، وكذلك في أي حالات أخرى تحتاج فيها الكائنات إلى المقارنة. يقارن التنفيذ الافتراضي للطريقة equals()
في الفصل المراجع java.lang.Object
بعناوين الذاكرة التي تخزنها المتغيرات ويعيدها true
فقط إذا كانت العناوين متطابقة، بمعنى آخر، تشير المتغيرات إلى نفس الكائن. توصي Java بتجاوز الأساليب " equals()
و" hashCode()
إذا كنت تتوقع إجراء المقارنة وفقًا للمنطق الطبيعي أو منطق الأعمال. تتجاوزها العديد من الفئات في مكتبات Java القياسية، على سبيل المثال، String
تتجاوز الفئة equals
بحيث يتم إرجاعها true
إذا كانت محتويات الكائنين اللذين تتم مقارنتهما متماثلين. تتجاوز فئة المجمع Integer
طريقة equal
إجراء مقارنة رقمية، وما إلى ذلك. نظرًا لأن Java تعتمد HashMap
أيضًا على طرق للمقارنة بين و ، فإن Java تقدم القواعد التالية لتجاوز هذه الطرق: HashTable
equals()
hashCode()
key
values
- الانعكاسية: يجب أن يكون الجسم مساوياً لنفسه.
- متماثل: إذا
a.equals(b)
عادtrue
فيجبb.equals(a)
أن يعود أيضًاtrue
. - العبور: إذا
a.equals(b)
عادtrue
وعادb.equals(c)
أيضاًtrue
،c.equals(a)
فلا بد أن يعود أيضاًtrue
. - الاتساق: يجب أن تُرجع الاستدعاءات المتكررة للطريقة
equals()
نفس القيمة طالما لم تتغير بعض قيم خصائص الكائن. أي أنه إذا كان هناك كائنان متساويان في Java، فسيكونان متساويين طالما ظلت خصائصهما دون تغيير. - المقارنة
null
: يجب التحقق من الكائنnull
. إذا كان الكائن يساويnull
، فيجب أن ترجع الطريقةfalse
، وليسNullPointerException
. على سبيل المثال،a.equals(null)
يجب أن يعودfalse
.
اتفاق بين يساوي و hashCode في جافا
- إذا كانت الكائنات متساوية في نتائج تنفيذ الطريقة
equals
،hashcode
فيجب أن تكون هي نفسها. - إذا لم تكن الكائنات متساوية في نتائج تنفيذ الطريقة
equals
، فيمكنhashcode
أن تكون متماثلة أو مختلفة. ومع ذلك، لتحسين الأداء، من الأفضل أن تقوم كائنات مختلفة بإرجاع رموز مختلفة.
كيفية تجاوز طريقة يساوي في جافا
-
@Override public boolean equals(Object obj) { /*1. Check*/
if (obj == this) { /*and return */ return true; }
-
Проверьте an object на
null
, а также проверьте, чтобы an objectы были одного типа. Не делайте проверку с помощьюinstanceof
так How такая проверка будет возвращатьtrue
для подклассов и будет работать правильно только в случае если ваш класс объявлен Howimmutable
. Вместо этого можно использоватьgetClass()
;if (obj == null || obj.getClass() != this.getClass()) { return false; }
-
Объявите переменную типа, который вы сравниваете, и приведите
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()))); }
/** * 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
-
Вместо того, чтобы переопределять метод
equals (Override)
программист перегружает его(Overload)
Синтаксис методаequals()
в классеObject
определен Howpublic boolean equals(Object obj)
, но многие программисты ненароком перегружают метод:public boolean equals(Person obj)
- instead ofObject
в качестве аргумента используют Name своего класса (напр. Person). Эту ошибку сложно обнаружить из-заstatic binding
. Таким образом, если вы вызовете этот метод для an object своего класса, то метод не просто скомпorруется, а даже сделает это корректно. Однако, если вы положите ваш an object в коллекцию, напримерArrayList
и вызовете методcontains()
, работа которого основана на методеequals()
, то методcontains
не сможет обнаружить ваш an object. -
При переопределении метода
equals()
не проверять наnull
переменные, что в конечном итоге заканчиваетсяNullPointerException
при вызовеequals()
. Ниже представлен корректный code.firstname == guest.firstname || (firstname != null && firstname.equals(guest.firstname));
-
Третья распространенная ошибка это не переопределять метод
hashCode()
, а толькоequals()
. Вы обязаны переопределять оба методаequals()
иhashCode()
в Java. МетодhashCode
используется вhash
-коллекциях(напримерHashSet
), и чем меньше будет коллизий (одинаковый code при разных an objectх) тем эффективнее эти коллекции будут работать с an objectми вашего класса. -
Последняя распространенная ошибка программистов в том, что при переопределении метода
equals()
не сохраняется соответствие между методамиequals()
иcompareTo()
, что является неформальным требованием для избежания хранения дубликатов вSet (SortedSet, TreeSet)
.
Подсказки How писать в Java метод equals
-
Большинство IDE такие How NetBeans, Eclipse и IntelliJ IDEA обеспечивают поддержку генерации методов
equals()
иhashCode()
. В Eclipse нажмите правую кнопку -> source ->generate equals()
иhashCode()
. -
Если в классе есть уникальный бизнес-ключ, то будет достаточно сделать проверку только на equalsство этих полей. Как в нашем примере “id” - уникальный номер для каждого Person.
-
При переопределении
hashCode()
в Java удостоверьтесь в использовании всех полей, что были использованы в методеequals()
. -
String
وفئات المجمعة مثلInteger
،Float
وتجاوزDouble
الطريقةequals()
، ولكنهاStringBuffer
لا تتجاوز. -
كلما أمكن، قم بإنشاء الحقول
immutable
باستخدامfinal
المتغيرات في Java. -
عند مقارنة
String
الكائنات، استخدمequals()
عامل التشغيل . بدلاً من ذلك==
. -
لا يمكن أن يكون كائنان متساويان منطقيًا ولكن تم تحميلهما من كائنين مختلفين
ClassLoader
متساويين. تذكر أن التحقق من ذلكgetClass()
سيعودfalse
إذا كانت فئة المُحمل مختلفة. -
استخدم
@Override
التعليق التوضيحي أيضًا في الطريقةhashCode
.، لأن هذا يمنع الأخطاء الدقيقة مثل القيمة المرجعة لـint
. ومع ذلك، يقوم بعض المبرمجين بإرجاعlong
.
GO TO FULL VERSION