Confronta due oggetti con l'operatore .equals () e ==


85

Ho costruito una classe con un Stringcampo. Poi ho creato due oggetti e devo confrontarli usando l' ==operatore e .equals()anche io . Ecco cosa ho fatto:

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


}

Dopo la compilazione mostra due volte false come risultato. Perché è falso se i due oggetti hanno gli stessi campi - "test"?


7
A proposito, guardando equalse equals2: ogni volta che hai qualcosa del modulo if(a) { return true; } else { return false; }dovresti probabilmente scrivere return a.
yshavit

@yshavit Vuoi dire, con il passaggio da booleano a String?
Fastkowy

4
no, il tuo codice chiede se un booleano è vero e restituisce truese lo è e falsealtrimenti. Quindi, per esempio, if(a.equals(object2)) { return true; } else return falsepotrebbe essere return a.equals(object2).
yshavit

Risposte:


142

==confronta i riferimenti agli oggetti, controlla se i due operandi puntano allo stesso oggetto (oggetti non equivalenti , lo stesso oggetto).

Se vuoi confrontare le stringhe (per vedere se contengono gli stessi caratteri), devi confrontare le stringhe usando equals.

Nel tuo caso, se due istanze di MyClasssono realmente considerate uguali se le stringhe corrispondono, allora:

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

... ma di solito se stai definendo una classe, c'è di più nell'equivalenza rispetto all'equivalenza di un singolo campo ( ain questo caso).


Nota a margine: se si esegue l'override equals, è quasi sempre necessario eseguire l'override hashCode. Come si dice nel equalsJavaDoc :

Si noti che è generalmente necessario sovrascrivere il hashCodemetodo ogni volta che questo metodo viene sovrascritto, in modo da mantenere il contratto generale per il hashCodemetodo, che afferma che oggetti uguali devono avere codici hash uguali.


@TJ In == confronta i riferimenti agli oggetti, per elaborare, Significa == confronta il codice hash dei due oggetti?
Narendra Jaggi

@NarendraJaggi - No, significa che la JVM verifica se i due operandi si riferiscono entrambi allo stesso oggetto. Il modo in cui lo fa dipende dalla JVM, ma non c'è motivo di pensare che userebbe un hashcode per farlo.
TJ Crowder

19

Dovresti sovrascrivere equals

 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
Questa è probabilmente la risposta migliore, tuttavia potresti voler usare this.equals (obj) invece di (this == null) per i tipi non primitivi
goonerify

10
Direi che il if (this == null)caso non è comunque necessario; la chiamata nullObject.equals(whatever)genererà un'eccezione del puntatore nullo, quindi possiamo tranquillamente presumere che thisnon sia nullo in nessun metodo Java che possiamo scrivere.
Maura

5

Sembra che equals2stia solo chiamando equals, quindi darà gli stessi risultati.


1
OP sta chiamando il equalsmetodo della String ache è un membro della classe. equals2non sta chiamandoequals
Yigit Alparslan

1
Sì grazie. Sembra che mi sia perso del tutto la confusione tra MyClass e String che è il vero problema.
Hew Wolff

5

La funzione di sovrascrittura equals () è sbagliata. L'oggetto "a" è un'istanza della classe String e "object2" è un'istanza della classe MyClass . Sono classi diverse, quindi la risposta è "falsa".


5

Il modo migliore per confrontare 2 oggetti è convertirli in stringhe JSON e confrontare le stringhe, è la soluzione più semplice quando si ha a che fare con complicati oggetti annidati, campi e / o oggetti che contengono array.

campione:

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
Vorrei chiamare questo: overkill.
Rolf ツ

@Rolf ツ Perché questo è eccessivo secondo te? Ho cercato una soluzione a questo problema e questa è la soluzione più semplice che ho trovato finora. Eventuali suggerimenti migliori sono i benvenuti.
m5seppal

3
Perché con Java puoi confrontare oggetti senza prima creare un Gsonoggetto e poi chiamare toJson. Creare l' Gsonoggetto e chiamare la logica necessaria per convertire l'oggetto effettivo in un flat String( toJson) non è un sovraccarico necessario. Puoi confrontare gli oggetti senza prima convertirli in stringhe Json (che è anche più veloce).
Rolf ツ

3

Il tuo equals2()metodo restituirà sempre lo stesso di equals()!!

Il tuo codice con i miei commenti:

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
Soloreturn a.equals(object2);
mojuba

2

Dichiarazioni a == object2ed a.equals(object2)entrambe torneranno sempre falseperché aè un stringistante object2diMyClass


2

La tua implementazione deve apprezzare:

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

Con questa implementazione entrambi i metodi funzionerebbero.


2

Se non è necessario personalizzare la funzione predefinita toString (), un altro modo è sovrascrivere il metodo toString (), che restituisce tutti gli attributi da confrontare. quindi confrontare con l'output di String () di due oggetti. Ho generato il metodo toString () utilizzando IntelliJ IDEA IDE, che include il nome della classe nella stringa.

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

L'operatore "==" restituisce true solo se i due riferimenti puntano allo stesso oggetto in memoria. Il metodo equals () d'altra parte restituisce true in base al contenuto dell'oggetto.

Esempio:

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

Risultato: confronto di due stringhe con == operatore: false Confronto di due stringhe con lo stesso contenuto utilizzando il metodo uguale: true Confronto di due riferimenti che puntano alla stessa stringa con == operatore: true

Puoi anche ottenere maggiori dettagli dal link: http://javarevisited.blogspot.in/2012/12/difference-between-equals-method-and-equality-operator-java.html?m=1


2

La tua classe potrebbe implementare l'interfaccia Comparable per ottenere la stessa funzionalità. La tua classe dovrebbe implementare il metodo compareTo () dichiarato nell'interfaccia.

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

il tipo restituito di object.equals è già booleano. non è necessario avvolgerlo in un metodo con rami. quindi se vuoi confrontare 2 oggetti semplicemente confrontali:

boolean b = objectA.equals(objectB);

b è già vero o falso.


1

Quando usiamo ==, il riferimento dell'oggetto viene confrontato non gli oggetti reali. Abbiamo bisogno di sovrascrivere il metodo uguale per confrontare gli oggetti Java.

Alcune informazioni aggiuntive C ++ ha l'operatore sul caricamento e Java non fornisce l'operatore sul caricamento. Anche altre possibilità in java sono implementare l' interfaccia di confronto, che definisce un metodo compareTo.

L'interfaccia del comparatore viene utilizzata anche per confrontare due oggetti


4
Considera che la tua risposta non aggiunge nulla che non sia stato detto quasi 2 anni fa.
Hot Licks

1

Qui l'output sarà falso, falso perché nella prima istruzione sopln stai provando a confrontare una variabile di tipo stringa di tipo Myclass con l'altro tipo MyClass e lo consentirà perché entrambi sono di tipo Object e hai usato l'operatore "==" che controllerà il valore della variabile di riferimento che contiene la memoria effettiva e non i contnet effettivi all'interno della memoria. Anche nel secondo sopln è lo stesso che stai chiamando di nuovo a.equals (object2) dove a è una variabile all'interno di object1. Fammi sapere le tue scoperte su questo.


2
Benvenuto in stackoverflow bidyadhar. La domanda è datata 14/11/2012 e ha già ottenuto una buona risposta (approvata da OP). Quello che hai ottenuto è corretto, ma non aggiunge informazioni utili. Ti consiglio di leggere le regole prima di fare qualsiasi cosa
Nikaido

-3

Nel codice seguente stai chiamando il metodo sovrascritto .equals ().

public boolean equals2 (Object object2) {if (a.equals (object2)) {// qui stai chiamando il metodo overriden, ecco perché ottieni false 2 volte. restituire vero; } altrimenti restituisce false; }


1
No, a.equalsè il metodo della stringa, non è sovrascritto da nessuna parte.
Tarec
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.