Hoje veremos as diferenças entre o método Equals e o operador de igualdade (==). Porém, antes de partir para a definição vamos recordar um conceito fundamental: Os tipos de dados no .Net Framework podem ser classificados de acordo com o fato de uma variável de um tipo específico armazenar seus próprios dados ou um ponteiro para os dados. Se a variável armazena seus próprios dados, é um tipo de valor, e se ela contém um ponteiro para dados em outro lugar na memória, é um tipo de referência. Além disso, você pode atribuir um tipo de referência ou um tipo de valor a uma variável do tipo de dados Object. Agora vamos definir Equals e o operador de igualdade (conforme a MSDN). 1 – EqualsO método Equals determina se o objeto especificado é igual ao objeto atual. O tipo de comparação entre a instância atual e o obj parâmetro depende se a instância atual é umtipo de referência (1) ou um tipo de valor (2).
2 – Operador ==Para tipos de valor predefinidos, o operador de igualdade (==) retornará true se os valores dos seus operandos forem iguais. Caso contrário, false. Para tipos de referência diferentes de string, o == retornará true se seus dois operandos se referirem ao mesmo objeto. Para o tipo string, o operador == compara os valores das cadeias de caracteres. Comparando tipos por valorPara valor e por tipo, o operador == e o método Equals() funcionam da mesma maneira: ambos comparam dois objetos por valor. Quando você compara tipos de valor, ou seja, tipos de dados primitivos (int, double, etc) usando o operador “==” ou o método “Equals”, a comparação é feita sempre com base no conteúdo. No código abaixo você pode ver que os dois métodos de comparação retornam ambos o mesmo valor: “true”. Comparando tipos por referênciaAgora, quando você compara objetos, eles são comparados com base na referência (ponteiro da memória interna). Abaixo temos a comparação entre oPessoa1 e oPessoa2 usando o operador “==” e o método “Equals”, e ambos retornarão false. Assim, embora ambos objetos tenham um nome de propriedade igual a “Macoratti”, eles ainda não serão iguais, uma vez que a comparação é baseada na referência da memória interna, que é diferente para “oPessoa1” e “oPessoa2“. Mas existe uma diferença no tratamento para objetos por referência. No exemplo abaixo temos que o operador == retorna false, pois ambas as referências apontam para objetos diferentes. Já o método Equals() compara os objetos por valor e retorna true, pois as referências dos objetos são equivalentes. Então, quando usar o operador == e quando usar o método Equals()? O operador “==” é apenas um operador C#, enquanto “Equals” é um método polimórfico. Em outras palavras, “==” é um recurso de linguagem, enquanto “Equals” é um recurso de programação orientada a objetos que segue o polimorfismo. Dessa forma, a comparação pode se feita com base em duas abordagens:
Por exemplo, 1 é diferente de 4 (1 <> 4) numericamente falando, mas 1 real vale 4 dólares (atualmente) semanticamente falando. Com base nisso, se você está procurando por uma comparação técnica, use o operador “==” a maior parte do tempo. Neste cenário, o operador “==” é suficiente, já que desenvolvedores fazem principalmente comparações técnicas. Se você está comparando semanticamente, então você precisa usar a lógica de comparação semântica e neste cenário você precisa usar o método “Equals” para comparar. E estamos conversados! De 0 a 10, o quanto você recomendaria este artigo para um amigo?
Um objeto é uma instância de uma classe que tem seu estado e comportamento. Em java, sendo orientado a objetos, é sempre criado dinamicamente e destruído automaticamente pelo coletor de lixo quando o escopo do objeto termina. Ilustração: Um exemplo para ilustrar um objeto de uma classe:
Abordagens: Existem dois métodos padrão: Exemplo 1: Embora o método equals() possa ser usado para comparar os valores de duas strings, não é realmente útil por padrão comparar dois objetos sem substituí-los. // Java Program to compare two objects // Importing java input output library import java.io.*; // Class 1 class Pet { // attributes of class1 String name; int age; String breed; // constructor of class 1 Pet(String name, int age, String breed) { // Assignment of current attributes /// using this keyword with same this.name = name; this.age = age; this.breed = breed; } } /* Class 2 : where execution is shown for class 1 */ public class GFG { // Main driver method public static void main(String args[]) { // Objects of class1 (auxiliary class) // are assigned value */ Pet dog1 = new Pet("Snow", 3, "German Shepherd"); Pet cat = new Pet("Jack", 2, "Tabby"); Pet dog2 = new Pet("Snow", 3, "German Shepherd"); // Checking objects are equal and // printing output- true/false System.out.println(dog1.equals(dog2)); } }Exemplo 2: Substituindo o método equals() Embora os valores de dog1 e dog2 sejam os mesmos, o método equals() sempre verifica a referência dos dois objetos, ou seja, se ambos os objetos passados referem-se ao mesmo objeto ou não e não aos seus valores. Portanto, é aconselhável não usar esse método na comparação de objetos sem substituí-lo. Implementando o método equals para o exemplo anterior: // Java Program to Compare Two Objects import java.io.*; class Pet { String name; int age; String breed; Pet(String name, int age, String breed) { this.name = name; this.age = age; this.breed = breed; } @Override public boolean equals(Object obj) { // checking if the two objects // pointing to same object if (this == obj) return true; // checking for two condition: // 1) object is pointing to null // 2) if the objects belong to // same class or not if (obj == null || this.getClass() != obj.getClass()) return false; Pet p1 = (Pet)obj; // type casting object to the // intended class type // checking if the two // objects share all the same values return this.name.equals(p1.name) && this.age == p1.age && this.breed.equals(p1.breed); } } public class GFG { public static void main(String args[]) { Pet dog1 = new Pet("Snow", 3, "German Shepherd"); Pet cat = new Pet("Jack", 2, "Tabby"); Pet dog2 = new Pet("Snow", 3, "German Shepherd"); System.out.println(dog1.equals(dog2)); } }Exemplo 3: No exemplo acima, o método equals() verifica se todos os valores correspondem ou não. No entanto, ele pode ser substituído de qualquer maneira possível, ou seja, se um ou dois valores corresponderem, etc. Por exemplo, se quisermos verificar quaisquer dois valores para fazer com que o método equals() considere os dois objetos iguais: // Java Program to Compare Two Objects // Importing java input/output libraries import java.io.*; // Class 1 class Pet { // Attributes of objects String name; int age; String breed; // Constructor Pet(String name, int age, String breed) { // Assigning current there it self // using this keyword this.name = name; this.age = age; this.breed = breed; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || this.getClass() != obj.getClass()) return false; Pet p1 = (Pet)obj; // Checking only if attribute- name // and age is same and ignoring breed return this.name.equals(p1.name) && this.age == p1.age; } } public class GFG { // Main driver method public static void main(String args[]) { // Assigning values to attributes of object // of class 1 Pet dog1 = new Pet("Snow", 3, "German Shepherd"); Pet cat1 = new Pet("Jack", 2, "Tabby"); Pet dog2 = new Pet("Snow", 3, "German Shepherd"); Pet cat2 = new Pet("Jack", 2, "Persian"); // Checking if object are equal and // printing boolean output System.out.println(cat1.equals(cat2)); } }Usando hashCode() e equals() Este método é mais como um complemento ao anterior. Verificar os valores de hash usando hashCode() antes de inserir equals() reduz drasticamente o tempo necessário para produzir a solução. Dessa forma, muitas comparações entre dois objetos não precisam passar pela comparação de todos os valores dentro deles. Exemplo 1: A implementação acima junto com o uso de hashCode() : // Java Program to Compare Two Objects // Importing java input/output libraries import java.io.*; // Class 1 class Pet { // Attributes of objects of class String name; int age; String breed; // Constructor Pet(String name, int age, String breed) { this.name = name; this.age = age; this.breed = breed; } // Overriding using hashCode() method @Override public int hashCode() { /* overriding hashCode() method to check the length of the names */ return this.name.length() % 10; } // Boolean function to check @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || this.getClass() != obj.getClass()) return false; Pet p1 = (Pet)obj; return this.name.equals(p1.name) && this.age == p1.age && this.breed == p1.breed; } } // main class (class2) public class GFG { // Main driver method public static void main(String args[]) { // Assigning values to object of class 1(Pet class) Pet dog1 = new Pet("Snow", 3, "German Shepherd"); Pet cat1 = new Pet("Jack", 2, "Tabby"); Pet dog2 = new Pet("Snow", 3, "German Shepherd"); Pet cat2 = new Pet("Jack", 2, "Persian"); /* hashCode() generates true as the lengths of the name value of the two objects are same*/ // Condition check using hashCode() method if (dog1.hashCode() == cat1.hashCode()) /* On entering equals() method, it checks for other values and hence, returns false */ System.out.println(dog1.equals(cat1)); else System.out.println("Not equal"); } }Exemplo 2: // Java Program to Compare Two Objects import java.io.*; class Pet { String name; int age; String breed; Pet(String name, int age, String breed) { this.name = name; this.age = age; this.breed = breed; } @Override public int hashCode() { // overriding hashCode() method to first // check the length of the names*/ return this.name.length() % 10; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || this.getClass() != obj.getClass()) return false; Pet p1 = (Pet)obj; return this.name.equals(p1.name) && this.age == p1.age && this.breed == p1.breed; } } public class GFG { public static void main(String args[]) { Pet dog1 = new Pet("Snow", 3, "German Shepherd"); Pet cat1 = new Pet("Jack", 2, "Tabby"); Pet dog2 = new Pet("Snow", 3, "German Shepherd"); Pet cat2 = new Pet("Jack", 2, "Persian"); Pet dog3 = new Pet("Ray", 1, "Siberian Husky"); // here, hashCode() generates false and condition // reverts to the else statement as soon as it finds out // the lengths of the name value of the objects are // differenT if (dog1.hashCode() == dog3.hashCode()) System.out.println(dog1.equals(dog3)); else System.out.println("Not equal"); } } |