Como Verificar se Dois Objetos São Iguais em Java

JavaBeginner
Pratique Agora

Introdução

Neste laboratório, você aprenderá como verificar se dois objetos são iguais em Java. Exploraremos a diferença fundamental entre o uso do operador == e o método equals() para comparação de objetos.

Você começará usando o método equals() embutido para comparar objetos e entender seu comportamento com diferentes tipos de dados. Em seguida, aprenderá como sobrescrever o método equals() em suas próprias classes personalizadas para definir o que constitui igualdade lógica para seus objetos. Finalmente, abordará a importante consideração de lidar com objetos nulos ao realizar verificações de igualdade para evitar potenciais erros NullPointerException.

Use o Método equals() para Igualdade

Nesta etapa, exploraremos como comparar objetos em Java usando o método equals(). Enquanto o operador == verifica se duas referências de objeto apontam para o mesmo objeto exato na memória, o método equals() é projetado para verificar se dois objetos são logicamente iguais, o que significa que eles representam o mesmo valor ou estado.

Vamos começar criando um arquivo Java simples para demonstrar este conceito.

  1. Abra o WebIDE e certifique-se de que está no diretório ~/project. Você pode confirmar isso olhando para o prompt do terminal ou digitando pwd e pressionando Enter.

  2. Crie um novo arquivo chamado EqualityDemo.java no diretório ~/project. Você pode fazer isso clicando com o botão direito no File Explorer à esquerda e selecionando "New File", em seguida, digitando EqualityDemo.java.

  3. Abra o arquivo EqualityDemo.java no editor e cole o seguinte código:

    public class EqualityDemo {
        public static void main(String[] args) {
            String str1 = new String("hello");
            String str2 = new String("hello");
            String str3 = str1;
    
            System.out.println("Comparing String objects:");
            System.out.println("str1 == str2: " + (str1 == str2));
            System.out.println("str1.equals(str2): " + str1.equals(str2));
            System.out.println("str1 == str3: " + (str1 == str3));
            System.out.println("str1.equals(str3): " + str1.equals(str3));
    
            System.out.println("\nComparing primitive types (int):");
            int num1 = 10;
            int num2 = 10;
            System.out.println("num1 == num2: " + (num1 == num2));
        }
    }

    Neste código:

    • Criamos dois objetos String, str1 e str2, com o mesmo conteúdo ("hello"), mas usando new String(), o que cria objetos distintos na memória.
    • Criamos uma terceira referência String, str3, e fazemos com que ela aponte para o mesmo objeto que str1.
    • Usamos tanto == quanto equals() para comparar str1 e str2, e str1 e str3.
    • Também mostramos uma comparação de tipos primitivos int usando ==. Lembre-se de que equals() é usado para objetos, não para tipos primitivos.
  4. Salve o arquivo EqualityDemo.java (Ctrl+S ou Cmd+S).

  5. Abra o Terminal na parte inferior do WebIDE.

  6. Compile o programa Java digitando o seguinte comando e pressionando Enter:

    javac EqualityDemo.java

    Se não houver erros, você não deverá ver nenhuma saída.

  7. Execute o programa compilado digitando o seguinte comando e pressionando Enter:

    java EqualityDemo

    Você deverá ver uma saída semelhante a esta:

    Comparing String objects:
    str1 == str2: false
    str1.equals(str2): true
    str1 == str3: true
    str1.equals(str3): true
    
    Comparing primitive types (int):
    num1 == num2: true

    Observe que str1 == str2 é false porque eles são objetos diferentes na memória, embora tenham o mesmo conteúdo. No entanto, str1.equals(str2) é true porque o método equals() da classe String é sobrescrito para comparar o conteúdo real das strings. str1 == str3 é true porque str3 aponta para o mesmo objeto exato que str1.

Isso demonstra a diferença fundamental entre == (igualdade de referência) e equals() (igualdade lógica) ao comparar objetos em Java. Para tipos primitivos, == é usado para comparação de valores.

Substituir equals() em Classe Personalizada

Na etapa anterior, vimos como o método equals() funciona para objetos String. A classe String já substituiu o método equals() padrão (herdado da classe Object) para fornecer uma comparação significativa com base no conteúdo.

No entanto, ao criar suas próprias classes personalizadas, o método equals() padrão herdado de Object simplesmente usa o operador ==, o que significa que ele só verifica a igualdade de referência. Para comparar objetos de sua classe personalizada com base em seus atributos (igualdade lógica), você precisa sobrescrever o método equals() você mesmo.

Nesta etapa, criaremos uma classe Person simples e substituiremos seu método equals().

  1. Certifique-se de que está no diretório ~/project no WebIDE.

  2. Crie um novo arquivo chamado Person.java no diretório ~/project.

  3. Abra Person.java e cole o seguinte código para a classe Person:

    public class Person {
        private String name;
        private int age;
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    
        // Default equals() method (inherited from Object) would only check reference equality
        // We need to override it to check for logical equality based on name and age
        @Override
        public boolean equals(Object obj) {
            // Step 1: Check if the objects are the same instance
            if (this == obj) {
                return true;
            }
    
            // Step 2: Check if the object is null or of a different class
            if (obj == null || getClass() != obj.getClass()) {
                return false;
            }
    
            // Step 3: Cast the object to the correct type
            Person person = (Person) obj;
    
            // Step 4: Compare the relevant attributes
            return age == person.age &&
                   name.equals(person.name); // Use equals() for String comparison
        }
    }

    Nesta classe Person:

    • Temos dois atributos privados: name (String) e age (int).
    • Temos um construtor para inicializar esses atributos.
    • Temos métodos getter para acessar os atributos.
    • Substituímos o método equals(). Vamos analisar as etapas dentro do equals() sobrescrito:
      • if (this == obj): Esta é uma otimização. Se as duas referências apontarem para o mesmo objeto exato, elas definitivamente são iguais.
      • if (obj == null || getClass() != obj.getClass()): Isso verifica se o objeto que está sendo comparado é nulo ou se não é uma instância da classe Person. Se qualquer um for verdadeiro, eles não podem ser iguais.
      • Person person = (Person) obj;: Convertemos o Object genérico em um objeto Person para que possamos acessar seus atributos name e age.
      • return age == person.age && name.equals(person.name);: Este é o núcleo da comparação lógica. Verificamos se a age é a mesma (usando == para o int primitivo) e se o name é o mesmo (usando equals() para objetos String).
  4. Salve o arquivo Person.java.

  5. Agora, vamos criar outro arquivo, PersonEqualityDemo.java, para testar nosso método equals() sobrescrito. Crie este arquivo no diretório ~/project.

  6. Abra PersonEqualityDemo.java e cole o seguinte código:

    public class PersonEqualityDemo {
        public static void main(String[] args) {
            Person person1 = new Person("Alice", 30);
            Person person2 = new Person("Alice", 30);
            Person person3 = new Person("Bob", 25);
            Person person4 = person1;
    
            System.out.println("Comparing Person objects:");
            System.out.println("person1 == person2: " + (person1 == person2));
            System.out.println("person1.equals(person2): " + person1.equals(person2));
            System.out.println("person1 == person3: " + (person1 == person3));
            System.out.println("person1.equals(person3): " + person1.equals(person3));
            System.out.println("person1 == person4: " + (person1 == person4));
            System.out.println("person1.equals(person4): " + person1.equals(person4));
        }
    }

    Nesta classe de demonstração, criamos vários objetos Person e os comparamos usando tanto == quanto nosso método equals() sobrescrito.

  7. Salve o arquivo PersonEqualityDemo.java.

  8. Abra o Terminal. Certifique-se de que está em ~/project.

  9. Compile ambos os arquivos Java. Você pode compilar vários arquivos de uma vez:

    javac Person.java PersonEqualityDemo.java

    Isso deve criar os arquivos Person.class e PersonEqualityDemo.class.

  10. Execute o programa de demonstração:

    java PersonEqualityDemo

    Você deverá ver uma saída semelhante a esta:

    Comparing Person objects:
    person1 == person2: false
    person1.equals(person2): true
    person1 == person3: false
    person1.equals(person3): false
    person1 == person4: true
    person1.equals(person4): true

    Como esperado, person1 == person2 é false porque eles são objetos distintos, mas person1.equals(person2) é true porque seus name e age são os mesmos de acordo com nosso método sobrescrito. person1 e person3 não são iguais por nenhuma das comparações. person1 e person4 são iguais por ambas as comparações porque se referem ao mesmo objeto.

Ao substituir o método equals(), você define o que "igual" significa para objetos de sua classe personalizada com base em seu estado lógico, em vez de apenas sua localização na memória.

Lidar com Objetos Nulos em Igualdade

Na etapa anterior, substituímos com sucesso o método equals() em nossa classe Person para comparar objetos com base em seus atributos. Um aspecto crucial de escrever métodos equals() robustos é lidar com valores null potenciais. Se você tentar chamar um método em um objeto null, isso resultará em um NullPointerException, que é um erro comum em Java.

Nosso método equals() substituído em Person.java já inclui uma verificação para null: if (obj == null || getClass() != obj.getClass()). Esta é a maneira padrão de lidar com o caso em que o objeto que está sendo comparado é null.

Nesta etapa, demonstraremos o que acontece ao comparar um objeto com null e confirmaremos que nosso método equals() o trata corretamente.

  1. Certifique-se de que está no diretório ~/project no WebIDE.

  2. Abra o arquivo PersonEqualityDemo.java que você criou na etapa anterior.

  3. Adicione as seguintes linhas ao método main, após as instruções de comparação existentes:

    System.out.println("\nComparing with null:");
    System.out.println("person1.equals(null): " + person1.equals(null));

    Este código simplesmente adiciona uma comparação de person1 com null.

  4. Salve o arquivo PersonEqualityDemo.java.

  5. Abra o Terminal. Certifique-se de que está em ~/project.

  6. Compile o arquivo PersonEqualityDemo.java modificado:

    javac PersonEqualityDemo.java

    Lembre-se de que você só precisa recompilar os arquivos que você alterou. Como Person.java não foi alterado nesta etapa, só precisamos compilar PersonEqualityDemo.java.

  7. Execute o programa compilado:

    java PersonEqualityDemo

    Você deverá ver a saída anterior seguida pela nova comparação com nulo:

    Comparing Person objects:
    person1 == person2: false
    person1.equals(person2): true
    person1 == person3: false
    person1.equals(person3): false
    person1 == person4: true
    person1.equals(person4): true
    
    Comparing with null:
    person1.equals(null): false

    A saída person1.equals(null): false confirma que nosso método equals() substituído lida corretamente com a comparação com null e retorna false sem lançar um NullPointerException. Isso ocorre porque a linha if (obj == null || getClass() != obj.getClass()) no método equals() da nossa classe Person verifica se é null antes de tentar acessar quaisquer atributos de obj.

Lidar com null é uma parte crítica de escrever código robusto em Java, especialmente ao lidar com comparações de objetos. Sempre inclua uma verificação null no início do seu método equals() substituído.

Resumo

Neste laboratório, aprendemos como verificar se dois objetos são iguais em Java. Começamos entendendo a diferença entre o operador ==, que verifica a igualdade de referência, e o método equals(), que verifica a igualdade lógica. Demonstramos isso usando objetos String e tipos primitivos, observando como == se comporta de forma diferente de equals() para objetos.

Em seguida, exploramos como substituir o método equals() em classes personalizadas para definir nossos próprios critérios para a igualdade de objetos. Isso é crucial para garantir que nossos objetos personalizados sejam comparados com base em seu conteúdo ou estado, em vez de apenas sua localização na memória. Finalmente, aprendemos a importância de lidar com objetos nulos dentro do método equals() para evitar NullPointerException e garantir verificações de igualdade robustas.