Compare dois objetos com o operador .equals () e ==

85

Construí uma classe com um Stringcampo. Então criei dois objetos e tenho que compará-los usando o ==operador e .equals()também. Aqui está o que eu fiz:

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


}

Após a compilação, ele mostra duas vezes falso como resultado. Por que é falso se os dois objetos têm os mesmos campos - "teste"?

Fastkowy
fonte
7
A propósito, olhando para equalse equals2: sempre que tiver algo na forma, if(a) { return true; } else { return false; }você provavelmente deve apenas escrever return a.
yshavit
@yshavit Você quer dizer, com mudança de booleano para String?
Fastkowy de
4
não, seu código está perguntando se um booleano é verdadeiro e retornando truese for e falsecaso contrário. Então, por exemplo, if(a.equals(object2)) { return true; } else return falsepoderia apenas ser return a.equals(object2).
yshavit
1
possível duplicata de Como comparo strings em Java?
bjb568

Respostas:

142

==compara referências de objeto, ele verifica se os dois operandos apontam para o mesmo objeto (não objetos equivalentes , o mesmo objeto).

Se quiser comparar strings (para ver se contêm os mesmos caracteres), você precisa comparar as strings usando equals.

No seu caso, se duas instâncias de MyClassrealmente forem consideradas iguais se as strings corresponderem, então:

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

... mas geralmente se você está definindo uma classe, há mais equivalência do que a equivalência de um único campo ( aneste caso).


Observação lateral: se você substituir equals, quase sempre precisará substituir hashCode. Como diz no equalsJavaDoc :

Observe que geralmente é necessário substituir o hashCodemétodo sempre que este método for substituído, de modo a manter o contrato geral para o hashCodemétodo, que afirma que objetos iguais devem ter códigos hash iguais.

TJ Crowder
fonte
@TJ Em == compara referências de objeto, para elaborar, isso significa == compara o hashcode dos dois objetos?
Narendra Jaggi
@NarendraJaggi - Não, significa que a JVM verifica se os dois operandos se referem ao mesmo objeto. Como isso fica por conta da JVM, mas não há razão para pensar que ela usaria um código hash para fazer isso.
TJ Crowder
19

Você deve substituir igual

 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
fonte
2
Esta é provavelmente a melhor resposta, no entanto, você pode querer usar this.equals (obj) em vez de (this == null) para tipos não primitivos
goonerify
10
Eu diria que o if (this == null)caso é desnecessário de qualquer maneira; a chamada nullObject.equals(whatever)lançará uma exceção de ponteiro nulo, portanto, podemos assumir com segurança que thisnão é nulo em nenhum método Java que possamos escrever.
Maura
5

Parece que equals2está apenas chamando equals, então dará os mesmos resultados.

Hew Wolff
fonte
1
OP está chamando o equalsmétodo da String aque é membro da classe. equals2não está ligandoequals
Yigit Alparslan
1
Sim obrigado. Parece que perdi totalmente a confusão entre MyClass e String, que é o verdadeiro problema.
Hew Wolff
5

A função de substituição equals () está errada. O objeto "a" é uma instância da classe String e "object2" é uma instância da classe MyClass . Eles são classes diferentes, então a resposta é "falsa".

Jesús Talavera Portocarrero
fonte
5

A melhor maneira de comparar 2 objetos é convertê-los em strings json e comparar as strings. É a solução mais fácil ao lidar com objetos aninhados complicados, campos e / ou objetos que contêm matrizes.

amostra:

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
fonte
9
Eu gostaria de chamar isso de exagero.
Rolf ツ
@Rolf ツ Por que isso é exagero na sua opinião? Procurei uma solução para este problema e esta é a solução mais fácil que encontrei até agora. Quaisquer sugestões melhores são bem-vindas.
m5seppal
3
Porque com Java você pode comparar objetos sem primeiro criar um Gsonobjeto e depois chamar toJson. Criar o Gsonobjeto e chamar a lógica necessária para converter o objeto real em um flat String( toJson) é uma sobrecarga desnecessária. Você pode comparar objetos sem primeiro convertê-los em strings Json (que também é mais rápido).
Rolf ツ
3

Seu equals2()método sempre retornará o mesmo que equals()!!

Seu código com meus comentários:

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

As instruções a == object2e a.equals(object2)ambas sempre retornarão falseporque aé um stringtempo object2é uma instância deMyClass

ashish.al
fonte
2

Sua implementação deve gostar de:

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

Com essa implementação, seus dois métodos funcionariam.

Azhar Khan
fonte
2

Se você não precisa personalizar a função toString () padrão, outra maneira é sobrescrever o método toString (), que retorna todos os atributos a serem comparados. em seguida, compare a saída toString () de dois objetos. Eu gerei o método toString () usando IntelliJ IDEA IDE, que inclui o nome da classe na string.

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

O operador "==" retorna verdadeiro apenas se as duas referências apontam para o mesmo objeto na memória. O método equals (), por outro lado, retorna true com base no conteúdo do objeto.

Exemplo:

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

Saída: Comparando duas strings com o operador ==: false Comparando duas Strings com o mesmo conteúdo usando o método equals: true Comparando duas referências apontando para a mesma String com o operador ==: true

Você também pode obter mais detalhes no link: http://javarevisited.blogspot.in/2012/12/difference-between-equals-method-and-equality-operator-java.html?m=1

Madhan
fonte
2

Sua classe pode implementar a interface Comparable para obter a mesma funcionalidade. Sua classe deve implementar o método compareTo () declarado na 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
fonte
1

o tipo de retorno de object.equals já é booleano. não há necessidade de envolvê-lo em um método com branches. então, se você quiser comparar 2 objetos, simplesmente compare-os:

boolean b = objectA.equals(objectB);

b já é verdadeiro ou falso.

Cpt. Mirk
fonte
1

Quando usamos ==, a referência do objeto é comparada, não os objetos reais. Precisamos substituir o método equals para comparar objetos Java.

Algumas informações adicionais C ++ possui operador sobre carregamento e Java não fornece operador sobre carregamento. Também outras possibilidades em java são implementar Interface Compare. Que define um método compareTo.

A interface de comparação também é usada para comparar dois objetos

umesh atada
fonte
4
Considere que sua resposta não acrescenta nada que não tenha sido dito quase 2 anos atrás.
Hot Licks de
1

Aqui a saída será falsa, falsa porque na primeira instrução sopln você está tentando comparar uma variável do tipo string do tipo Myclass com o outro tipo MyClass e isso permitirá porque ambos são do tipo Object e você usou o operador "==" que irá verificar o valor da variável de referência que contém a memória real, não os contnets reais dentro da memória. Na segunda etapa, também é o mesmo que você está chamando novamente a.equals (objeto2), onde a é uma variável dentro do objeto1. Deixe-me saber suas descobertas sobre isso.

Bidyadhar
fonte
2
Bem-vindo ao stackoverflow bidyadhar. A questão data de 14/11/2012 e já obteve boa resposta (aprovada pelo OP). O que você obteve está correto, mas não está adicionando informações úteis. Eu sugiro que você leia as regras antes de fazer qualquer coisa
Nikaido
-3

No código abaixo, você está chamando o método sobrescrito .equals ().

public boolean equals2 (Object object2) {if (a.equals (object2)) {// aqui você está chamando o método sobrescrito, é por isso que você obtém false 2 vezes. return true; } senão retorna falso; }

RAM
fonte
1
Não, a.equalsé o método da string, não é sobrescrito em lugar nenhum.
Tarec