Substitution de la java de la méthode equals () - pas de travail?
J'ai couru dans une intéressante (et très frustrant) problème avec le equals()
méthode aujourd'hui, ce qui a causé ce que je pensais être un bien testé la classe de crash et de provoquer un bug qui m'a pris un temps très long à repérer.
Juste pour être complet, je n'étais pas à l'aide d'un IDE ou un débogueur - juste de la bonne vieille éditeur de texte et du Système.out. Le temps était très limité et que c'était un projet d'école.
De toute façon -
J'ai été l'élaboration d'une base panier qui pourrait contenir un ArrayList
de Book
objets. Afin de mettre en œuvre les addBook()
, removeBook()
, et hasBook()
méthodes de la Charrette, je voulais vérifier si le Book
existait déjà dans le Cart
. Donc me voilà -
public boolean equals(Book b) {
... //More code here - null checks
if (b.getID() == this.getID()) return true;
else return false;
}
Tous fonctionne très bien dans les tests. J'ai créer 6 objets et de les remplir avec des données. Faire beaucoup de ajoute, supprime, a() les opérations sur la Cart
et tout fonctionne bien. J'ai lu que vous pouvez soit equals(TYPE var)
ou equals(Object o) { (CAST) var }
mais suppose que depuis qu'il travaillait, il n'a pas trop d'importance.
Puis j'ai rencontré un problème - j'avais besoin de créer un Book
objet avec seulement la ID
à partir du Livre de classe. Pas d'autres données serait entré en elle. Essentiellement les suivantes:
public boolean hasBook(int i) {
Book b = new Book(i);
return hasBook(b);
}
public boolean hasBook(Book b) {
//.. more code here
return this.books.contains(b);
}
Tout d'un coup, le equals(Book b)
méthode ne fonctionne plus. Cela a pris un temps TRÈS long à repérer sans un bon débogueur et en supposant que le Cart
classe a été testé correctement et de les corriger. Après swaapping la equals()
méthode à la suivante:
public boolean equals(Object o) {
Book b = (Book) o;
... //The rest goes here
}
Tout a commencé à travailler à nouveau. Est-il une raison, la méthode décidé de ne pas prendre le Livre paramètre, même si c'est clairement la a un Book
objet? La seule différence semble être que c'était instancié à partir de l'intérieur de la même classe, et remplis avec un membre de données. Je suis très très confus. S'il vous plaît, jeter un peu de lumière?
- Je suis conscient que j'ai violé le "Contrat" concernant la substitution de l'égal des méthodes en cours de réflexion cependant j'ai besoin d'un moyen rapide de vérifier si l'objet existe dans la liste de tableaux sans l'aide de médicaments génériques.
- C'est une bonne leçon à apprendre Java et est égale à
Vous devez vous connecter pour publier un commentaire.
En Java, le
equals()
méthode est héritée deObject
est:En d'autres termes, le paramètre doit être de type
Object
.La
ArrayList
utilise la bonne méthode equals, où vous avez été toujours à l'appel de celui qui n'avait pas bien remplacerObject
s'est égal.Pas de substitution de la méthode correctement peut causer des problèmes.
Je remplace est égale à la suivante à chaque fois:
L'utilisation de la
@Override
annotation peut aider une tonne avec des erreurs stupides.De les utiliser quand vous pensez que vous êtes remplacement d'une super-classe ou de l'interface de la méthode. De cette façon, si vous le faites mal, vous obtiendrez une erreur de compilation.
if (!(other instanceof MyClass))return false;
retournefalse
siMyClass
s'étend de l'autre classe. Mais il ne serait pas de retourfalse
si l'autre classe étendueMyClass
. Ne devrait pasequal
être moins contradictoires?equals()
queo1.equals(o2)
doit retourner true uniquement sio2.equals(o1)
renvoie également vrai. sio1
est une instance d'une sous-classe deo2
,o1 instanceof o2
retourne vrai (et donc neo1.equals(o2)
), maiso2 instanceof o1
renvoie la valeur false,o2.equals(o1)
retourne false, et le contrat est rompu.equals()
de manière plus stricte.Si vous utilisez eclipse, allez simplement dans le menu du haut
Légèrement hors-sujet à votre question, mais c'est probablement la peine de mentionner quand même:
Commons Lang a obtenu quelques excellentes méthodes que vous pouvez utiliser en remplaçant equals et hashcode. Découvrez EqualsBuilder.reflectionEquals(...) et HashCodeBuilder.reflectionHashCode(...). M'a sauvé beaucoup de maux de tête dans le passé - même si bien sûr, si vous voulez juste faire "est synonyme de" ID il peut ne pas convenir à votre situation.
Je suis aussi d'accord que vous devriez utiliser le
@Override
annotation lorsque vous êtes primordial est égal à (ou toute autre méthode).right click -> source -> generate hashCode() and equals()
,Une autre solution rapide qui permet d'économiser du code réutilisable est Lombok EqualsAndHashCode annotation. Il est facile, élégant et personnalisable. Et ne dépend pas de l'IDE. Par exemple;
Voir le options disponible pour personnaliser les champs à utiliser dans les égaux. Lombok est dispo dans maven. Il suffit de l'ajouter avec fourni portée:
dans Android Studio est
alt + inser ---> equals et hashCode
Exemple:
Considérer:
obj
est déclaré comme unObject
. Le point de l'héritage est que vous pouvez ensuite affecter unBook
àobj
. Après que, à moins que vous suggèrent qu'uneObject
ne doit pas être comparable à unString
viaequals()
, ce code doit être parfaitement légal et retourfalse
.la
instanceOf
déclaration est souvent utilisé dans la mise en œuvre d'égal à égal.Ce populaire est un piège !
Le problème est que l'utilisation de
instanceOf
viole la règle de symétrie:(object1.equals(object2) == true)
si et seulement si(object2.equals(object1))
si le premier est égal à est vrai, et objet2 est une instance d'une sous-classe de
la classe où obj1 appartient, alors que la seconde est égal retournera false!
si l'considérée classe où l'ob1 appartient à est déclarée comme définitive, alors ce
le problème ne peut pas se poser, mais en général, vous devez tester comme suit:
this.getClass() != otherObject.getClass();
sinon, retourne false, sinon le testles champs de comparer pour l'égalité!
equals()
méthode. Il recommande à l'encontre de l'aidegetClass()
. La raison principale est qu'il rompt le Principe de Substitution de Liskov pour les sous-classes, qui n'affectent pas l'égalité.recordId est la propriété de l'objet