Como sobrescrever o método equals em java

Eu estou tentando replace o método equals em java. Eu tenho uma class People que basicamente tem 2 campos de dados nome e idade. Agora eu quero replace o método equals para que eu possa verificar entre 2 objects People.

Meu código é o seguinte

public boolean equals(People other){ boolean result; if((other == null) || (getClass() != other.getClass())){ result = false; } // end if else{ People otherPeople = (People)other; result = name.equals(other.name) && age.equals(other.age); } // end else return result; } // end equals 

Mas quando eu escrevo age.equals (other.age) me dá erro como método equals só pode comparar String e age é Integer.

Por favor me ajude a corrigir isso.

Obrigado é adiantado.

Eu usei o operador == como sugerido e meu problema está resolvido. Muito obrigado por me esforçar para me ajudar.

 //Written by K@stackoverflow public class Main { /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here ArrayList people = new ArrayList(); people.add(new Person("Subash Adhikari", 28)); people.add(new Person("K", 28)); people.add(new Person("StackOverflow", 4)); people.add(new Person("Subash Adhikari", 28)); for (int i = 0; i < people.size() - 1; i++) { for (int y = i + 1; y <= people.size() - 1; y++) { boolean check = people.get(i).equals(people.get(y)); System.out.println("-- " + people.get(i).getName() + " - VS - " + people.get(y).getName()); System.out.println(check); } } } } //written by K@stackoverflow public class Person { private String name; private int age; public Person(String name, int age){ this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (!Person.class.isAssignableFrom(obj.getClass())) { return false; } final Person other = (Person) obj; if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { return false; } if (this.age != other.age) { return false; } return true; } @Override public int hashCode() { int hash = 3; hash = 53 * hash + (this.name != null ? this.name.hashCode() : 0); hash = 53 * hash + this.age; return hash; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 

Saída:

corre:

- Subash Adhikari - VS - K falso

- Subash Adhikari - VS - StackOverflow false

- Subash Adhikari - VS - Subash Adhikari true

- K - VS - StackOverflow false

- K - VS - Subash Adhikari false

- StackOverflow - VS - Subash Adhikari false

- CONSTRUÇÃO BEM SUCEDIDA (tempo total: 0 segundos)

Primeiro de tudo: você não está ignorando os equals , você está sobrecarregando -o.

Sem ver a declaração real de age , é difícil dizer por que você está recebendo o erro.

Não tenho certeza dos detalhes, já que você não postou todo o código, mas:

  • lembre-se de replace o hashCode() também
  • o método equals deve ter Object , não People como seu tipo de argumento. No momento você está sobrecarregando, não sobrescrevendo, o método equals, que provavelmente não é o que você quer, especialmente considerando que você verifica seu tipo mais tarde.
  • você pode usar instanceof para verificar se é um object People, por exemplo, if (!(other instanceof People)) { result = false;}
  • equals é usado para todos os objects, mas não primitivos. Eu acho que você quer dizer que a idade é um int (primitivo), nesse caso apenas use == . Note que um Integer (com um capital ‘I’) é um object que deve ser comparado com iguais.

Veja quais problemas devem ser considerados ao replace equals e hashCode em Java? para mais detalhes.

 @Override public boolean equals(Object that){ if(this == that) return true;//if both of them points the same address in memory if(!(that instanceof People)) return false; // if "that" is not a People or a childclass People thatPeople = (People)that; // than we can cast it to People safely return this.name.equals(thatPeople.name) && this.age == thatPeople.age;// if they have the same name and same age, then the 2 objects are equal unless they're pointing to different memory adresses } 

Desde que eu estou supondo que a age é do tipo int :

 public boolean equals(Object other){ boolean result; if((other == null) || (getClass() != other.getClass())){ result = false; } // end if else{ People otherPeople = (People)other; result = name.equals(otherPeople.name) && age == otherPeople.age; } // end else return result; } // end equals 

Item 10: Obedecer ao contrato geral ao sobrepor

De acordo com o Effective Java , a substituição do método equals parece simples, mas há muitas maneiras de errar, e as consequências podem ser terríveis. A maneira mais fácil de evitar problemas é não sobrescrever o método equals , caso em que cada instância da class é igual a ela mesma. Esta é a coisa certa a fazer se alguma das seguintes condições se aplicar:

  • Cada instância da class é inerentemente exclusiva . Isso é verdade para classs como Thread, que representam entidades ativas em vez de valores. A implementação equals fornecida por Object tem exatamente o comportamento correto para essas classs.

  • Não há necessidade de a class fornecer um teste de “igualdade lógica”. Por exemplo, java.util.regex.Pattern poderia ter sobrescrito equals para verificar se duas instâncias Pattern representavam exatamente a mesma expressão regular, mas os designers não achavam que os clientes precisariam ou desejariam essa funcionalidade. Sob essas circunstâncias, a implementação de iguais herdada do object é ideal.

  • Uma superclass já substituiu equals e o comportamento da superclass é apropriado para essa class. Por exemplo, a maioria das implementações do Conjunto herdam sua implementação equals das implementações AbstractSet, List das implementações AbstractList e Map do AbstractMap.

  • A class é privada ou privada de pacote e você tem certeza de que seu método equals nunca será invocado. Se você é extremamente avesso ao risco, você pode replace o método equals para garantir que ele não seja invocado acidentalmente:

O método equals implementa uma relação de equivalência. Tem estas propriedades:

  • Reflexivo: Para qualquer valor de referência não nulo x , x.equals(x) deve retornar true.

  • Simétrica: Para quaisquer valores de referência não nulos x e y , x.equals(y) deve retornar true se e somente se y.equals (x) retornar true.

  • Transitivo: Para quaisquer valores de referência não nulos x , y , z , se x.equals(y) retornar true e y.equals(z) retornar true , então x.equals(z) deverá retornar true .

  • Consistente: Para qualquer valor de referência não nulo x e y , várias invocações de x.equals(y) devem consistentemente retornar true ou consistentemente retornar false , desde que nenhuma informação usada nas comparações de iguais seja modificada.

  • Para qualquer valor de referência não nulo x , x.equals(null) deve retornar false .

Aqui está uma receita para um método de igualdade de alta qualidade:

  1. Use o operador == para verificar se o argumento é uma referência a este object. Se sim, retorne verdadeiro. Esta é apenas uma otimização de desempenho, mas vale a pena fazê-lo se a comparação for potencialmente cara.

  2. Use o operador instanceof para verificar se o argumento possui o tipo correto. Se não, retorne false. Normalmente, o tipo correto é a class na qual o método ocorre. Ocasionalmente, é alguma interface implementada por esta class. Use uma interface se a class implementar uma interface que refina o contrato de igual para permitir comparações entre as classs que implementam a interface. As interfaces de coleta, como Set, List, Map e Map.Entry, possuem essa propriedade.

  3. Elenco o argumento para o tipo correto. Como esse casting foi precedido por um exemplo de teste, é garantido que ele será bem-sucedido.

  4. Para cada campo “significativo” da class, verifique se esse campo do argumento corresponde ao campo correspondente desse object. Se todos esses testes forem bem sucedidos, retorne verdadeiro; Caso contrário, retorne false. Se o tipo na Etapa 2 for uma interface, você deverá acessar os campos do argumento por meio de methods de interface; se o tipo for uma class, você poderá acessar os campos diretamente, dependendo de sua acessibilidade.

  5. Para campos primitivos cujo tipo não é float ou double , use o operador == para comparações; para campos de referência de object, chame o método equals recursivamente; para campos float , use o Float.compare(float, float) estático Float.compare(float, float) ; e para campos double , use Double.compare(double, double) . O tratamento especial dos campos float e double é feito necessário pela existência de Float.NaN , -0.0f e os valores duplos análogos; Embora você possa comparar os campos float e double com os methods estáticos Float.equals e Double.equals , isso implicaria o uso de autoboxing em todas as comparações, o que teria um desempenho ruim. Para campos de array , aplique essas diretrizes a cada elemento. Se cada elemento em um campo de matriz for significativo, use um dos methods Arrays.equals .

  6. Alguns campos de referência de object podem conter legitimamente null . Para evitar a possibilidade de um NullPointerException , verifique esses campos para igualdade usando o método estático Objects.equals(Object, Object) .

     // Class with a typical equals method public final class PhoneNumber { private final short areaCode, prefix, lineNum; public PhoneNumber(int areaCode, int prefix, int lineNum) { this.areaCode = rangeCheck(areaCode, 999, "area code"); this.prefix = rangeCheck(prefix, 999, "prefix"); this.lineNum = rangeCheck(lineNum, 9999, "line num"); } private static short rangeCheck(int val, int max, String arg) { if (val < 0 || val > max) throw new IllegalArgumentException(arg + ": " + val); return (short) val; } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof PhoneNumber)) return false; PhoneNumber pn = (PhoneNumber)o; return pn.lineNum == lineNum && pn.prefix == prefix && pn.areaCode == areaCode; } ... // Remainder omitted } 

Ao comparar objects em Java, você faz uma verificação semântica , comparando o tipo e identificando o estado dos objects para:

  • em si (mesma instância)
  • próprio (clone ou cópia reconstruída)
  • outros objects de diferentes tipos
  • outros objects do mesmo tipo
  • null

Regras:

  • Simetria : a.equals(b) == b.equals(a)
  • equals() sempre produz true ou false , mas nunca um NullpointerException , ClassCastException ou qualquer outro throwable

Comparação:

  • Verificação de tipo : ambas as instâncias precisam ser do mesmo tipo, ou seja, você deve comparar as classs reais por igualdade. Isso geralmente não é implementado corretamente, quando os desenvolvedores usam instanceof para comparação de tipo (que funciona somente enquanto não houver subclasss e viola a regra de simetria quando A extends B -> a instanceof b != b instanceof a) .
  • Verificação semântica do estado de identificação : certifique-se de entender por qual estado as instâncias são identificadas. As pessoas podem ser identificadas pelo seu número de segurança social, mas não pela cor do cabelo (pode ser tingido), nome (pode ser alterado) ou idade (muda o tempo todo). Somente com objects de valor você deve comparar o estado completo (todos os campos não transientes), caso contrário, verifique somente o que identifica a instância.

Para sua class Person :

 public boolean equals(Object obj) { // same instance if (obj == this) { return true; } // null if (obj == null) { return false; } // type if (!getClass().equals(obj.getClass())) { return false; } // cast and compare state Person other = (Person) obj; return Objects.equals(name, other.name) && Objects.equals(age, other.age); } 

Classe de utilitário reutilizável e genérica:

 public final class Equals { private Equals() { // private constructor, no instances allowed } /** * Convenience equals implementation, does the object equality, null and type checking, and comparison of the identifying state * * @param instance object instance (where the equals() is implemented) * @param other other instance to compare to * @param stateAccessors stateAccessors for state to compare, optional * @param  instance type * @return true when equals, false otherwise */ public static  boolean as(T instance, Object other, Function< ? super T, Object>... stateAccessors) { if (instance == null) { return other == null; } if (instance == other) { return true; } if (other == null) { return false; } if (!instance.getClass().equals(other.getClass())) { return false; } if (stateAccessors == null) { return true; } return Stream.of(stateAccessors).allMatch(s -> Objects.equals(s.apply(instance), s.apply((T) other))); } } 

Para sua class Person , usando esta class de utilitário:

 public boolean equals(Object obj) { return Equals.as(this, obj, t -> t.name, t -> t.age); } 

Se age for int você deve usar == se for object Integer, então você pode usar equals (). Você também precisa implementar o método hashcode se você replace equals. Detalhes do contrato estão disponíveis no javadoc de Object e também em várias páginas da web.

O método equals define um parâmetro de método do tipo Object e seu tipo de retorno é booleano.

 Don't change the name of the method, its return type, or the type of method parameter 

quando você define ( sobrescreve ) este método em sua class para comparar dois objects.

 public boolean equals(Object anObject) { ... }