Vergleichen Sie zwei Objekte mit den Operatoren .equals () und ==


84

Ich habe eine Klasse mit einem StringFeld aufgebaut. Dann habe ich zwei Objekte erstellt und muss sie auch mit dem ==Operator vergleichen .equals(). Folgendes habe ich getan:

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));
    }


}

Nach dem Kompilieren wird als Ergebnis zweimal false angezeigt. Warum ist es falsch, wenn die beiden Objekte die gleichen Felder haben - "Test"?


7
Btw, betrachten equalsund equals2: jedes Mal , wenn etwas von der Form haben , if(a) { return true; } else { return false; }sollten Sie wahrscheinlich nur schreiben return a.
Yshavit

@yshavit Du meinst, mit Wechsel von Boolean zu String?
Fastkowy

4
Nein, Ihr Code fragt, ob ein Boolescher Wert wahr ist, und gibt zurück, trueob dies der Fall ist und falsenicht. So könnte es zum Beispiel if(a.equals(object2)) { return true; } else return falseeinfach sein return a.equals(object2).
Yshavit

Antworten:


142

==Vergleicht Objektreferenzen und prüft, ob die beiden Operanden auf dasselbe Objekt verweisen (keine äquivalenten Objekte, dasselbe Objekt).

Wenn Sie Zeichenfolgen vergleichen möchten (um festzustellen, ob sie dieselben Zeichen enthalten), müssen Sie die Zeichenfolgen mit vergleichen equals.

In Ihrem Fall, wenn zwei Instanzen von MyClasswirklich als gleich angesehen werden, wenn die Zeichenfolgen übereinstimmen, dann:

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

... aber normalerweise, wenn Sie eine Klasse definieren, ist Äquivalenz mehr als die Äquivalenz eines einzelnen Feldes ( ain diesem Fall).


Randnotiz: Wenn Sie überschreiben equals, müssen Sie fast immer überschreiben hashCode. Wie es im equalsJavaDoc heißt :

Beachten Sie, dass es im Allgemeinen erforderlich ist, die hashCodeMethode zu überschreiben , wenn diese Methode überschrieben wird, um den allgemeinen Vertrag für die hashCodeMethode beizubehalten , der besagt, dass gleiche Objekte gleiche Hash-Codes haben müssen.


@TJ In == vergleicht Objektreferenzen, um näher darauf einzugehen. Bedeutet dies, dass == den Hashcode der beiden Objekte vergleicht?
Narendra Jaggi

@NarendraJaggi - Nein, dies bedeutet, dass die JVM prüft, ob sich beide Operanden auf dasselbe Objekt beziehen. Wie das geht, hängt von der JVM ab, aber es gibt keinen Grund zu der Annahme, dass dafür ein Hashcode verwendet wird.
TJ Crowder

19

Sie sollten gleich überschreiben

 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());
 }

2
Dies ist wohl die beste Antwort, aber Sie möchten vielleicht this.equals (obj) anstelle von (this == null) für nicht primitive Typen verwenden
goonerify

10
Ich würde argumentieren, dass der if (this == null)Fall sowieso unnötig ist; Der Aufruf nullObject.equals(whatever)löst eine Nullzeigerausnahme aus, sodass wir davon ausgehen können, dass thisdiese in keiner Java-Methode, die wir schreiben, null ist.
Maura

1
dies wird fehlschlagen , wenn this hat lastnamenull und nicht vorherige Bedingungen erfüllen.
Ahmed Raaj

6

Es sieht so aus, equals2als würde nur angerufen equals, sodass die gleichen Ergebnisse erzielt werden.


5

Die Überschreibungsfunktion equals () ist falsch. Das Objekt "a" ist eine Instanz der String- Klasse und "object2" ist eine Instanz der MyClass- Klasse. Sie sind verschiedene Klassen, daher lautet die Antwort "falsch".


5

Der beste Weg, um 2 Objekte zu vergleichen, besteht darin, sie in JSON-Zeichenfolgen zu konvertieren und die Zeichenfolgen zu vergleichen. Dies ist die einfachste Lösung, wenn Sie mit komplizierten verschachtelten Objekten, Feldern und / oder Objekten arbeiten, die Arrays enthalten.

Stichprobe:

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
}

9
Ich würde das gerne Overkill nennen.
Rolf

@Rolf ツ Warum ist das deiner Meinung nach übertrieben? Ich habe nach einer Lösung für dieses Problem gesucht und dies ist die einfachste Lösung, die ich bisher gefunden habe. Bessere Vorschläge sind willkommen.
m5seppal

3
Denn mit Java können Sie Objekte vergleichen, ohne zuerst ein GsonObjekt zu erstellen und dann aufzurufen toJson. Das Erstellen des GsonObjekts und das Aufrufen der Logik, die zum Konvertieren des tatsächlichen Objekts in eine flat String( toJson) erforderlich ist, ist kein unnötiger Aufwand. Sie können Objekte vergleichen, ohne die Objekte zuerst in Json-Zeichenfolgen zu konvertieren (was auch schneller ist).
Rolf ツ

3

Ihre equals2()Methode gibt immer die gleiche zurück wie equals()!!

Ihr Code mit meinen Kommentaren:

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
}

5
Justreturn a.equals(object2);
Mojuba

2

Anweisungen a == object2und a.equals(object2)beide werden immer zurückgegeben, falseda aeine stringWeile object2eine Instanz von istMyClass


2

Ihre Implementierung muss wie folgt aussehen:

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

Mit dieser Implementierung würden beide Methoden funktionieren.


2

Wenn Sie die Standardfunktion toString () nicht anpassen müssen, können Sie auch die Methode toString () überschreiben, die alle zu vergleichenden Attribute zurückgibt. Vergleichen Sie dann die Ausgabe von String () von zwei Objekten. Ich habe die toString () -Methode mit IntelliJ IDEA IDE generiert, die den Klassennamen in der Zeichenfolge enthält.

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 + '\'' +
            '}';
}
}

2

Der Operator "==" gibt nur dann true zurück, wenn die beiden Referenzen auf dasselbe Objekt im Speicher verweisen. Die Methode equals () gibt dagegen basierend auf dem Inhalt des Objekts true zurück.

Beispiel:

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);

Ausgabe: Vergleichen von zwei Zeichenfolgen mit dem Operator ==: false Vergleichen von zwei Zeichenfolgen mit demselben Inhalt mit der Methode equals: true Vergleichen von zwei Referenzen, die auf denselben String zeigen, mit dem Operator ==: true

Weitere Informationen erhalten Sie auch über den Link: http://javarevisited.blogspot.in/2012/12/difference-between-equals-method-and-equality-operator-java.html?m=1


2

Ihre Klasse implementiert möglicherweise die Schnittstelle Comparable, um dieselbe Funktionalität zu erzielen. Ihre Klasse sollte die in der Schnittstelle deklarierte compareTo () -Methode implementieren.

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");
        }
    }
}

1

Der Rückgabetyp von object.equals ist bereits boolesch. Es ist nicht erforderlich, es in eine Methode mit Zweigen zu verpacken. Wenn Sie also 2 Objekte vergleichen möchten, vergleichen Sie sie einfach:

boolean b = objectA.equals(objectB);

b ist bereits entweder wahr oder falsch.


1

Wenn wir == verwenden, wird die Referenz des Objekts verglichen, nicht die tatsächlichen Objekte. Wir müssen die Methode equals überschreiben, um Java-Objekte zu vergleichen.

Einige zusätzliche Informationen C ++ verfügt über einen Operator zum Laden und Java bietet keinen Operator zum Laden. Weitere Möglichkeiten in Java sind die Implementierung der Vergleichsschnittstelle, die eine compareTo-Methode definiert.

Die Komparatorschnittstelle wird auch verwendet, um zwei Objekte zu vergleichen


4
Bedenken Sie, dass Ihre Antwort nichts hinzufügt, was vor fast 2 Jahren noch nicht gesagt wurde.
Hot Licks

1

Hier ist die Ausgabe falsch, falsch, weil in der ersten sopln-Anweisung Sie versuchen, eine Zeichenfolgentypvariable vom Typ Myclass mit dem anderen MyClass-Typ zu vergleichen, und dies ermöglicht, da beide Objekttypen sind und Sie den Operator "==" verwendet haben prüft den Referenzvariablenwert, der den tatsächlichen Speicher enthält, nicht die tatsächlichen Contnets im Speicher. Auch im zweiten sopln ist es dasselbe, als würden Sie wieder a.equals (object2) aufrufen, wobei a eine Variable innerhalb von object1 ist. Teilen Sie mir Ihre diesbezüglichen Erkenntnisse mit.


2
Willkommen bei stackoverflow bidyadhar. Die Frage ist vom 14.11.2012 und hat bereits eine gute Antwort erhalten (vom OP genehmigt). Die, die Sie erhalten haben, ist korrekt, fügt jedoch keine nützlichen Informationen hinzu. Ich schlage vor, dass Sie die Regeln lesen, bevor Sie etwas tun
Nikaido

-3

Im folgenden Code rufen Sie die Überschreibungsmethode .equals () auf.

public boolean equals2 (Object object2) {if (a.equals (object2)) {// Hier rufen Sie die Overriden-Methode auf, weshalb Sie zweimal false erhalten. return true; } else return false; }}


1
Nein, a.equalsist die Methode von string, sie wird nirgendwo überschrieben.
Tarec
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.