Comparez deux objets avec les opérateurs .equals () et ==

84

J'ai construit une classe avec un Stringchamp. Ensuite, j'ai créé deux objets et je dois les comparer à l'aide de l' ==opérateur et .equals()aussi. Voici ce que j'ai fait:

public class MyClass {

    String a;

    public MyClass(String ab) {
        a = ab;
    }

    public boolean equals(Object object2) {
        if(a == object2) { 
            return true;
        }
        else return false;
    }

    public boolean equals2(Object object2) {
        if(a.equals(object2)) {
            return true;
        }
        else return false;
    }



    public static void main(String[] args) {

        MyClass object1 = new MyClass("test");
        MyClass object2 = new MyClass("test");

        object1.equals(object2);
        System.out.println(object1.equals(object2));

        object1.equals2(object2);
        System.out.println(object1.equals2(object2));
    }


}

Après la compilation, il affiche deux fois faux en conséquence. Pourquoi est-il faux si les deux objets ont les mêmes champs - "test"?

Fastkowy
la source
7
Btw, en regardant equalset equals2: chaque fois que vous avez quelque chose de la forme, if(a) { return true; } else { return false; }vous devriez probablement simplement écrire return a.
yshavit
@yshavit Vous voulez dire, avec le changement de booléen en chaîne?
Fastkowy
4
non, votre code demande si un booléen est un vrai, et retourne truesi c'est le cas et falseautrement. Ainsi, par exemple, if(a.equals(object2)) { return true; } else return falsepourrait simplement être return a.equals(object2).
yshavit
1
duplication possible de Comment comparer des chaînes en Java?
bjb568

Réponses:

142

==compare les références d'objets, il vérifie si les deux opérandes pointent vers le même objet (objets non équivalents , même objet).

Si vous souhaitez comparer des chaînes (pour voir si elles contiennent les mêmes caractères), vous devez comparer les chaînes à l'aide de equals.

Dans votre cas, si deux instances de MyClassreally sont considérées comme égales si les chaînes correspondent, alors:

public boolean equals(Object object2) {
    return object2 instanceof MyClass && a.equals(((MyClass)object2).a);
}

... mais généralement, si vous définissez une classe, l'équivalence ne se résume pas à l'équivalence d'un seul champ ( adans ce cas).


Remarque: si vous remplacez equals, vous devez presque toujours annuler hashCode. Comme il est dit dans le equalsJavaDoc :

Notez qu'il est généralement nécessaire de remplacer la hashCodeméthode chaque fois que cette méthode est remplacée, afin de conserver le contrat général de la hashCodeméthode, qui stipule que les objets égaux doivent avoir des codes de hachage égaux.

TJ Crowder
la source
@TJ In == compare les références d'objets, pour élaborer, cela signifie-t-il que == compare le hashcode des deux objets?
Narendra Jaggi
@NarendraJaggi - Non, cela signifie que la JVM vérifie si les deux opérandes font référence au même objet. Comment faire cela dépend de la JVM, mais il n'y a aucune raison de penser qu'elle utiliserait un hashcode pour le faire.
TJ Crowder
19

Vous devez remplacer les égaux

 public boolean equals (Object obj) {
     if (this==obj) return true;
     if (this == null) return false;
     if (this.getClass() != obj.getClass()) return false;
     // Class name is Employ & have lastname
     Employe emp = (Employee) obj ;
     return this.lastname.equals(emp.getlastname());
 }
user5119219
la source
2
C'est sans doute la meilleure réponse, mais vous voudrez peut-être utiliser this.equals (obj) au lieu de (this == null) pour les types non primitifs
goonerify
10
Je dirais que le if (this == null)cas est inutile de toute façon; L'appel nullObject.equals(whatever)va lancer une exception de pointeur nul, nous pouvons donc supposer en toute sécurité que ce thisn'est pas nul dans toute méthode Java que nous pouvons écrire.
Maura
1
cela échouera si this a lastnamenull et ne satisfait pas les conditions précédentes.
Ahmed Raaj
6

On dirait que equals2c'est juste un appel equals, donc ça donnera les mêmes résultats.

Hew Wolff
la source
5

La fonction d'écrasement equals () est incorrecte. L'objet "a" est une instance de la classe String et "object2" est une instance de la classe MyClass . Ce sont des classes différentes, donc la réponse est "fausse".

Jesús Talavera Portocarrero
la source
5

La meilleure façon de comparer 2 objets est de les convertir en chaînes json et de comparer les chaînes, c'est la solution la plus simple lorsqu'il s'agit d'objets imbriqués compliqués, de champs et / ou d'objets contenant des tableaux.

échantillon:

import com.google.gson.Gson;


Object a = // ...;
Object b = //...;
String objectString1 = new Gson().toJson(a);
String objectString2 = new Gson().toJson(b); 

if(objectString1.equals(objectString2)){
    //do this
}
JoeG
la source
9
Je voudrais appeler cela: exagéré.
Rolf ツ
@Rolf ツ Pourquoi est-ce exagéré à votre avis? J'ai cherché une solution à ce problème et c'est la solution la plus simple que j'ai trouvée jusqu'à présent. Toutes les meilleures suggestions sont les bienvenues.
m5seppal
3
Parce qu'avec Java, vous pouvez comparer des objets sans créer d'abord un Gsonobjet, puis appeler toJson. La création de l' Gsonobjet et l'appel de la logique nécessaire pour convertir l'objet réel en flat String( toJson) est une surcharge inutile. Vous pouvez comparer des objets sans d'abord convertir les objets en chaînes Json (ce qui est également plus rapide).
Rolf ツ
3

Votre equals2()méthode retournera toujours la même chose que equals()!!

Votre code avec mes commentaires:

public boolean equals2(Object object2) {  // equals2 method
    if(a.equals(object2)) { // if equals() method returns true
        return true; // return true
    }
    else return false; // if equals() method returns false, also return false
}
jlordo
la source
5
Justreturn a.equals(object2);
mojuba
2

Les déclarations a == object2et les a.equals(object2)deux seront toujours renvoyées falsecar ais a stringwhile object2est une instance deMyClass

ashish.al
la source
2

Votre implémentation doit aimer:

public boolean equals2(Object object2) {
    if(a.equals(object2.a)) {
        return true;
    }
    else return false;
}

Avec cette implémentation, vos deux méthodes fonctionneraient.

Azhar Khan
la source
2

Si vous n'avez pas besoin de personnaliser la fonction toString () par défaut, une autre méthode consiste à remplacer la méthode toString (), qui renvoie tous les attributs à comparer. puis comparez la sortie toString () de deux objets. J'ai généré la méthode toString () en utilisant IntelliJ IDEA IDE, qui inclut le nom de la classe dans la chaîne.

public class Greeting {
private String greeting;

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    return this.toString().equals(obj.toString());
}

@Override
public String toString() {
    return "Greeting{" +
            "greeting='" + greeting + '\'' +
            '}';
}
}
Qinjie
la source
2

L'opérateur "==" renvoie true uniquement si les deux références pointant vers le même objet en mémoire. La méthode equals (), quant à elle, renvoie true en fonction du contenu de l'objet.

Exemple:

String personalLoan = new String("cheap personal loans");
String homeLoan = new String("cheap personal loans");

//since two strings are different object result should be false
boolean result = personalLoan == homeLoan;
System.out.println("Comparing two strings with == operator: " + result);

//since strings contains same content , equals() should return true
result = personalLoan.equals(homeLoan);
System.out.println("Comparing two Strings with same content using equals method: " + result);

homeLoan = personalLoan;
//since both homeLoan and personalLoan reference variable are pointing to same object
//"==" should return true
result = (personalLoan == homeLoan);
System.out.println("Comparing two reference pointing to same String with == operator: " + result);

Sortie: comparaison de deux chaînes avec l'opérateur ==: false Comparaison de deux chaînes avec le même contenu à l'aide de la méthode equals: true Comparaison de deux références pointant vers la même chaîne avec l'opérateur ==: true

Vous pouvez également obtenir plus de détails sur le lien: http://javarevisited.blogspot.in/2012/12/difference-between-equals-method-and-equality-operator-java.html?m=1

Madhan
la source
2

Votre classe peut implémenter l'interface Comparable pour obtenir la même fonctionnalité. Votre classe doit implémenter la méthode compareTo () déclarée dans l'interface.

public class MyClass implements Comparable<MyClass>{

    String a;

    public MyClass(String ab){
        a = ab;
    }

    // returns an int not a boolean
    public int compareTo(MyClass someMyClass){ 

        /* The String class implements a compareTo method, returning a 0 
           if the two strings are identical, instead of a boolean.
           Since 'a' is a string, it has the compareTo method which we call
           in MyClass's compareTo method.
        */

        return this.a.compareTo(someMyClass.a);

    }

    public static void main(String[] args){

        MyClass object1 = new MyClass("test");
        MyClass object2 = new MyClass("test");

        if(object1.compareTo(object2) == 0){
            System.out.println("true");
        }
        else{
            System.out.println("false");
        }
    }
}
tf3
la source
1

le type de retour de object.equals est déjà booléen. il n'est pas nécessaire de l'envelopper dans une méthode avec des branches. donc si vous souhaitez comparer 2 objets, comparez-les simplement:

boolean b = objectA.equals(objectB);

b est déjà vrai ou faux.

Cpt. Obscur
la source
1

Lorsque nous utilisons ==, la référence de l'objet n'est pas comparée aux objets réels. Nous devons remplacer la méthode equals pour comparer les objets Java.

Quelques informations supplémentaires C ++ a un opérateur sur le chargement et Java ne fournit pas d'opérateur sur le chargement. D'autres possibilités en java sont l'implémentation de Compare Interface .qui définit une méthode compareTo.

L'interface de comparaison est également utilisée pour comparer deux objets

umesh atada
la source
4
Considérez que votre réponse n'ajoute rien qui n'ait été dit il y a près de 2 ans.
Hot Licks
1

Ici, la sortie sera fausse, fausse car dans la première instruction sopln, vous essayez de comparer une variable de type chaîne de type Myclass à l'autre type MyClass et cela permettra car les deux sont de type Object et vous avez utilisé l'opérateur "==" qui vérifiera la valeur de la variable de référence contenant la mémoire réelle et non les contnets réels à l'intérieur de la mémoire. Dans le second sopln, c'est la même chose que vous appelez à nouveau a.equals (object2) où a est une variable à l'intérieur de object1. Faites-moi savoir vos conclusions à ce sujet.

Bidyadhar
la source
2
Bienvenue dans stackoverflow bidyadhar. La question est datée du 14/11/2012 et a déjà reçu une bonne réponse (approuvée par OP). Celui que vous avez obtenu est correct, mais il n'ajoute pas d'informations utiles. Je vous suggère de lire les règles avant de faire quoi que ce soit
Nikaido
-3

Dans le code ci-dessous, vous appelez la méthode overriden .equals ().

public boolean equals2 (Object object2) {if (a.equals (object2)) {// ici vous appelez la méthode overriden, c'est pourquoi vous obtenez false 2 fois. retourne vrai; } else return false; }

RAM
la source
1
Non, a.equalsc'est la méthode de string, elle n'est remplacée nulle part.
Tarec