Dominando a Comparação de Strings em Java: Diferença entre “==”, equals(), compareTo() e Melhores Práticas

1. Introdução

Por que a comparação de strings é importante em Java?

Na programação Java, strings são usadas em muitas situações. Verificar nomes de usuário, validar a entrada de formulários e confirmar respostas de APIs exigem a comparação de strings.
Neste ponto, “como comparar strings corretamente” é um obstáculo comum para iniciantes. Em particular, não entender a diferença entre o operador == e o método equals() pode levar a bugs inesperados.

O perigo de não entender a diferença entre “==” e “equals”

Considere o seguinte código:

String a = "apple";
String b = new String("apple");

System.out.println(a == b);       // result: false
System.out.println(a.equals(b));  // result: true

Muitas pessoas ficam surpresas com esse resultado. Mesmo que as strings sejam idênticas, == retorna false enquanto equals() retorna true. Isso acontece porque o Java trata strings como tipos de referência, e == compara endereços de referência.
Entender a forma correta de comparar strings afeta diretamente a confiabilidade e a legibilidade do seu programa. Se você compreendê‑la adequadamente, pode prevenir bugs antes que ocorram.

O que você aprenderá neste artigo

Este artigo explica a comparação de strings em Java, desde o básico até aplicações práticas. Ele responde a perguntas como:

  • Qual é a diferença entre == e equals() ?
  • Como comparar strings ignorando maiúsculas/minúsculas?
  • Como comparar strings lexicograficamente?
  • Como evitar exceções ao comparar com null?

Através de exemplos do mundo real, você obterá uma compreensão sólida das práticas corretas de comparação de strings.

2. Conceitos Básicos de Strings em Java

Strings são tipos de referência

No Java, o tipo String não é um primitivo (como int ou boolean), mas um tipo de referência. Uma variável String não armazena os caracteres reais, mas uma referência a um objeto armazenado na memória heap.
Por exemplo:

String a = "hello";
String b = "hello";

Tanto a quanto b podem referir‑se ao mesmo literal "hello" devido ao mecanismo de internamento de strings do Java.

Diferença entre literais de string e new String()

O Java otimiza literais de string repetidos reutilizando a mesma referência:

String s1 = "apple";
String s2 = "apple";
System.out.println(s1 == s2); // true (same literal, interned)

Entretanto, usar new sempre cria um novo objeto:

String s3 = new String("apple");
System.out.println(s1 == s3); // false (different references)
System.out.println(s1.equals(s3)); // true (same content)

Assim, == verifica a referência e equals() verifica o conteúdo.

Strings são imutáveis

Outra característica importante é que String é imutável. Uma vez criada, a string não pode ser alterada.

String original = "hello";
original = original + " world";

Isso cria um novo objeto String ao invés de modificar o original.

3. Métodos para Comparar Strings

Comparando referências com ==

== compara referências de objetos:

String a = "Java";
String b = new String("Java");

System.out.println(a == b); // false

Ele não deve ser usado para comparação de conteúdo.

Comparando conteúdo com equals()

equals() é a forma correta de comparar o conteúdo de strings:

String a = "Java";
String b = new String("Java");

System.out.println(a.equals(b)); // true

Evitando NullPointerException

String input = null;
System.out.println(input.equals("test")); // Exception!

Use o estilo constante‑primeiro:

System.out.println("test".equals(input)); // false, safe

Ignorando maiúsculas/minúsculas com equalsIgnoreCase()

String a = "Hello";
String b = "hello";

System.out.println(a.equalsIgnoreCase(b)); // true

Comparação lexicográfica com compareTo()

  • 0 → igual
  • Negativo → o chamador precede
  • Positivo → o chamador segue
    String a = "apple";
    String b = "banana";
    
    System.out.println(a.compareTo(b)); // negative
    

4. Exemplos Práticos

Verificação de login de usuário

String inputUsername = "Naohiro";
String registeredUsername = "naohiro";

if (registeredUsername.equalsIgnoreCase(inputUsername)) {
    System.out.println("Login successful");
} else {
    System.out.println("Username does not match");
}

Senhas devem sempre usar equals() porque a sensibilidade a maiúsculas e minúsculas é necessária.

Validação de entrada de formulário

String selectedOption = request.getParameter("plan");

if ("premium".equals(selectedOption)) {
    System.out.println("Premium plan selected.");
} else {
    System.out.println("Other plan selected.");
}

Lógica de ramificação com múltiplas verificações de strings

String cmd = args[0];

if ("start".equals(cmd)) {
    startApp();
} else if ("stop".equals(cmd)) {
    stopApp();
} else {
    System.out.println("Invalid command");
}
switch (cmd) {
    case "start":
        startApp();
        break;
    case "stop":
        stopApp();
        break;
    default:
        System.out.println("Unknown command");
}

Tratamento seguro de null

String keyword = null;

if ("search".equals(keyword)) {
    System.out.println("Searching...");
}

5. Desempenho e Otimização

Custo das comparações de strings

equals() e compareTo() comparam caracteres internamente. Para strings longas ou comparações repetidas, isso pode afetar o desempenho.

Usando String.intern() para desempenho

String a = new String("hello").intern();
String b = "hello";

System.out.println(a == b); // true

Use apenas quando necessário para evitar pressão de memória.

Impacto de desempenho do equalsIgnoreCase()

String input = userInput.toLowerCase();
if ("admin".equals(input)) {
    // fast comparison
}

Usando StringBuilder / StringBuffer

StringBuilder sb = new StringBuilder();
sb.append("user_");
sb.append("123");

String result = sb.toString();

if (result.equals("user_123")) {
    // comparison
}

Usando cache ou mapas para reduzir comparações

Map<String, Runnable> commandMap = new HashMap<>();
commandMap.put("start", () -> startApp());
commandMap.put("stop", () -> stopApp());

Runnable action = commandMap.get(inputCommand);
if (action != null) {
    action.run();
}

6. Perguntas Frequentes

Q1. Qual é a diferença entre == e equals()?

A.

  • == compara referências
  • equals() compara o conteúdo da string

Q2. Por que o equals() lança um erro quando a variável é null?

String input = null;
input.equals("test"); // Exception

Use uma comparação constante-primeiro:

"test".equals(input);

Q3. Como comparar strings ignorando maiúsculas/minúsculas?

stringA.equalsIgnoreCase(stringB);

Q4. Como comparar ordem alfabética?

a.compareTo(b);

7. Conclusão

Escolher corretamente o método de comparação adequado é importante

Como String é um tipo de referência, comparações incorretas frequentemente levam a comportamentos inesperados. Entender == vs equals() é essencial.

Checklist

  • == : compara referências
  • equals() : compara conteúdo
  • equalsIgnoreCase() : ignora maiúsculas/minúsculas
  • compareTo() : ordem lexicográfica
  • "constant".equals(variable) : seguro contra null
  • Use intern() ou cache para comparações intensivas

Conhecimento prático e essencial

A comparação de strings aparece em verificações de login, validação, operações de banco de dados, lógica de ramificação e muitas tarefas diárias. Conhecer as técnicas corretas ajuda a escrever código mais seguro e confiável.

Use este guia como referência ao trabalhar com strings em Java.