Compare dos objetos con .equals () y == operador

84

Construí una clase con un Stringcampo. Luego creé dos objetos y tengo que compararlos usando el ==operador y .equals()también. Esto es lo que hice:

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


}

Después de la compilación, muestra dos veces falso como resultado. ¿Por qué es falso si los dos objetos tienen los mismos campos - "prueba"?

Fastkowy
fuente
7
Por cierto, mirando equalsy equals2: cada vez que tenga algo de la forma if(a) { return true; } else { return false; }, probablemente debería simplemente escribir return a.
yshavit
@yshavit ¿Quieres decir, con el cambio de booleano a String?
Fastkowy
4
no, su código pregunta si un booleano es verdadero y devuelve truesi lo es y de lo falsecontrario. Entonces, por ejemplo, if(a.equals(object2)) { return true; } else return falsepodría ser return a.equals(object2).
yshavit
1
posible duplicado de ¿Cómo comparo cadenas en Java?
bjb568

Respuestas:

142

==compara referencias de objetos, comprueba si los dos operandos apuntan al mismo objeto (no objetos equivalentes , el mismo objeto).

Si desea comparar cadenas (para ver si contienen los mismos caracteres), debe comparar las cadenas usando equals.

En su caso, si dos instancias de MyClassrealmente se consideran iguales si las cadenas coinciden, entonces:

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

... pero normalmente si está definiendo una clase, la equivalencia es más que la equivalencia de un solo campo ( aen este caso).


Nota al margen: si anula equals, casi siempre tendrá que anular hashCode. Como dice en equalsJavaDoc :

Tenga en cuenta que generalmente es necesario anular el hashCodemétodo siempre que este método se anula , para mantener el contrato general del hashCodemétodo, que establece que los objetos iguales deben tener códigos hash iguales.

TJ Crowder
fuente
@TJ In == compara referencias de objetos, para elaborar, ¿significa que == compara el código hash de los dos objetos?
Narendra Jaggi
@NarendraJaggi - No, significa que la JVM verifica si los dos operandos se refieren al mismo objeto. Cómo lo hace depende de la JVM, pero no hay razón para pensar que usaría un código hash para hacerlo.
TJ Crowder
19

Deberías anular los iguales

 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());
 }
usuario5119219
fuente
2
Esta es posiblemente la mejor respuesta, sin embargo, es posible que desee usar this.equals (obj) en lugar de (this == null) para tipos no primitivos
goonerify
10
Yo diría que el if (this == null)caso es innecesario de todos modos; la llamada nullObject.equals(whatever)arrojará una excepción de puntero nulo, por lo que podemos asumir con seguridad que thisno es nulo en ningún método Java que podamos escribir.
Maura
1
esto fallará cuando this tenga un lastnamevalor nulo y no satisfaga las condiciones previas.
Ahmed Raaj
6

Parece que equals2solo está llamando equals, por lo que dará los mismos resultados.

Hew Wolff
fuente
5

La función de sobrescritura igual a () es incorrecta. El objeto "a" es una instancia de la clase String y "object2" es una instancia de la clase MyClass . Son clases diferentes, por lo que la respuesta es "falsa".

Jesús Talavera Portocarrero
fuente
5

La mejor manera de comparar 2 objetos es convirtiéndolos en cadenas json y comparar las cadenas, es la solución más fácil cuando se trata de objetos anidados complicados, campos y / o objetos que contienen matrices.

muestra:

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
fuente
9
Me gustaría llamar a esto: overkill.
Rolf ツ
@Rolf ツ ¿Por qué esto es exagerado en tu opinión? He buscado una solución a este problema y esta es la solución más fácil que he encontrado hasta ahora. Cualquier sugerencia mejor es bienvenida.
m5seppal
3
Porque con Java puedes comparar objetos sin primero crear un Gsonobjeto y luego llamar toJson. Crear el Gsonobjeto y llamar a la lógica necesaria para convertir el objeto real en un plano String( toJson) es una sobrecarga innecesaria. Puede comparar objetos sin convertir primero los objetos en cadenas Json (que también es más rápido).
Rolf ツ
3

Tu equals2()método siempre devolverá el mismo que equals()!!

Tu código con mis comentarios:

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
fuente
5
Justreturn a.equals(object2);
mojuba
2

Declaraciones a == object2y a.equals(object2)ambas siempre regresarán falseporque aes un stringtiempo object2es una instancia deMyClass

ashish.al
fuente
2

Su implementación debe gustar:

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

Con esta implementación, ambos métodos funcionarían.

Azhar Khan
fuente
2

Si no necesita personalizar la función toString () predeterminada, otra forma es anular el método toString (), que devuelve todos los atributos a comparar. luego compare la salida toString () de dos objetos. Genere el método toString () usando IntelliJ IDEA IDE, que incluye el nombre de la clase en la cadena.

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
fuente
2

El operador "==" devuelve verdadero solo si las dos referencias apuntan al mismo objeto en la memoria. El método equals (), por otro lado, devuelve verdadero en función del contenido del objeto.

Ejemplo:

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

Resultado: comparar dos cadenas con == operador: falso Comparar dos cadenas con el mismo contenido usando el método igual: verdadero Comparar dos referencias que apuntan a la misma cadena con == operador: verdadero

También puede obtener más detalles en el enlace: http://javarevisited.blogspot.in/2012/12/difference-between-equals-method-and-equality-operator-java.html?m=1

Madhan
fuente
2

Su clase podría implementar la interfaz Comparable para lograr la misma funcionalidad. Su clase debe implementar el método compareTo () declarado en la interfaz.

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
fuente
1

el tipo de retorno de object.equals ya es booleano. no es necesario envolverlo en un método con ramas. así que si quieres comparar 2 objetos, simplemente compáralos:

boolean b = objectA.equals(objectB);

b ya es verdadero o falso.

Cpt. Tenebroso
fuente
1

Cuando usamos ==, la Referencia del objeto se compara, no los objetos reales. Necesitamos anular el método equals para comparar objetos Java.

Alguna información adicional C ++ tiene un operador sobre la carga y Java no proporciona un operador sobre la carga. También otras posibilidades en java son implementar Compare Interface, que define un método compareTo.

La interfaz del comparador también se utiliza para comparar dos objetos

umesh atada
fuente
4
Considere que su respuesta no agrega nada que no se haya dicho hace casi 2 años.
Hot Licks
1

Aquí la salida será falsa, falsa porque en la primera declaración sopln está tratando de comparar una variable de tipo de cadena de tipo Myclass con el otro tipo MyClass y lo permitirá debido a que ambos son de tipo Object y usted ha usado "==" oprerator que Verificará el valor de la variable de referencia que contiene la memoria real, no los contnets reales dentro de la memoria. En el segundo sopln también es lo mismo que está llamando de nuevo a.equals (object2) donde a es una variable dentro de object1. Hágame saber sus hallazgos sobre esto.

Bidyadhar
fuente
2
Bienvenido a stackoverflow bidyadhar. La pregunta está fechada el 14/11/2012 y ya obtuvo una buena respuesta (aprobada por OP). El que obtuvo es correcto, pero no agrega información útil. Te sugiero que leas las reglas antes de hacer nada
Nikaido
-3

EN el siguiente código, está llamando al método anulado .equals ().

public boolean equals2 (Object object2) {if (a.equals (object2)) {// aquí está llamando al método anulado, es por eso que obtiene falso 2 veces. devuelve verdadero; } si no devuelve falso; }

RAM
fuente
1
No, a.equalses el método de string, no se anula en ninguna parte.
Tarec