0Pricing
Java Academy · Aula

Imutabilidade de String e o Pool de Strings

Compreenda por que as Strings são imutáveis, como funciona o pool de strings e quando usar == em vez de equals.

Imutabilidade de String e o Pool de Strings é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.

Imutabilidade de String e o pool de strings

As strings são imutáveis em Java. Compreender a imutabilidade, o pool de strings e a igualdade de referências em comparação com a igualdade de valores evita erros sutis.

Por que as strings são imutáveis

Os objetos String não podem ser modificados após a criação. Qualquer operação que "altere" uma String, na verdade, cria um novo objeto String. Isso permite o compartilhamento, a segurança em ambientes concorrentes e o armazenamento em cache de hashCode.

String s = "hello";
s.toUpperCase(); // creates a new String, does NOT modify s
System.out.println(s); // still "hello"

String upper = s.toUpperCase(); // must capture the result
System.out.println(upper); // HELLO

O pool de strings (internação)

Os literais de string são armazenados no String Pool (uma seção especial do heap). Dois literais com o mesmo conteúdo compartilham o mesmo objeto.

String a = "hello"; // goes into pool
String b = "hello"; // same object from pool
String c = new String("hello"); // forces new object outside pool

System.out.println(a == b);       // true  (same pool reference)
System.out.println(a == c);       // false (different objects)
System.out.println(a.equals(c));  // true  (same content)

== versus equals()

Use sempre .equals() para comparar o conteúdo de uma String. O operador == verifica se duas variáveis apontam para o mesmo objeto (igualdade de referências).

String input = new String("admin"); // from user input, not pooled
String role  = "admin";

// Dangerous: fails because different objects
if (input == role) System.out.println("Same"); // not printed!

// Correct: compares content
if (input.equals(role)) System.out.println("Equal!"); // prints

// Null-safe: put constant first to avoid NPE
if ("admin".equals(input)) System.out.println("Admin"); // prints

intern(): colocar manualmente uma String no pool

String.intern() força uma String a entrar no pool e retorna a referência armazenada nele. Raramente é necessário em versões modernas do Java.

String s1 = new String("interned");
String s2 = s1.intern();
String s3 = "interned"; // already in pool

System.out.println(s2 == s3); // true (both point to pool)
System.out.println(s1 == s3); // false (s1 is off-pool)

// Modern use: prefer String.intern() only when you need
// identity-based caching with thousands of repeated strings

Comportamento da concatenação de strings

A concatenação com + cria novos objetos String. Dentro de um laço, isso resulta em O(n²). O compilador otimiza expressões únicas, mas não concatenações baseadas em laços.

// Compiler optimizes this to a StringBuilder automatically:
String result = "Hello, " + "World" + "!";

// In loops: compiler does NOT optimize — use StringBuilder explicitly!
List<String> words = List.of("a", "b", "c", "d");
String bad = ""; // O(n^2) — new object each iteration
for (String w : words) bad += w;

StringBuilder sb = new StringBuilder();
for (String w : words) sb.append(w); // O(n) — efficient
String good = sb.toString();
System.out.println(good); // abcd

Comparando strings corretamente

Use sempre equals(); para comparações que ignoram maiúsculas e minúsculas, use equalsIgnoreCase(). Use compareTo() para a ordenação lexicográfica.

String a = "Java";
String b = "java";

System.out.println(a.equals(b));             // false
System.out.println(a.equalsIgnoreCase(b));   // true
System.out.println(a.compareToIgnoreCase(b)); // 0 (equal)
System.out.println(a.compareTo(b));           // negative (J < j in Unicode)

Armazenamento em cache do hashCode de String

Como as strings são imutáveis, Java armazena o hashCode em cache após a primeira chamada. As chamadas seguintes retornam o valor armazenado em cache, tornando as strings muito eficientes como chaves de HashMap.

String key = "product:12345";
// hashCode computed once and cached:
int h1 = key.hashCode();
int h2 = key.hashCode(); // returns cached value
System.out.println(h1 == h2); // true

// Strings are ideal HashMap keys because:
// 1. hashCode is consistent (immutable content)
// 2. hashCode is cached (fast repeated lookups)
// 3. equals is well-defined (content-based)
Map<String, Integer> map = new HashMap<>();
map.put("key", 42);
System.out.println(map.get("key")); // 42

String é final

A classe String é final — não pode ser estendida. Isso garante que nenhuma subclasse possa violar a imutabilidade ou a consistência do hashCode.

// String is final — this will not compile:
// class MutableString extends String {} // compile error

// You cannot override String behavior.
// If you need custom string-like behavior, use a wrapper:
record ProductSku(String value) {
    ProductSku { if (!value.matches("[A-Z]{3}-[0-9]{4}")) throw new IllegalArgumentException(); }
    @Override public String toString() { return value; }
}

String.format versus concatenação

Para strings compostas por várias partes, prefira String.format() ou blocos de texto à concatenação, para obter mais clareza e facilitar a localização.

String name = "Alice";
int age = 30;
double score = 97.5;

// Concatenation — harder to read with many parts
String bad = "User: " + name + ", Age: " + age + ", Score: " + score;

// String.format — clear placeholders
String good = String.format("User: %s, Age: %d, Score: %.1f", name, age, score);

System.out.println(good);
// User: Alice, Age: 30, Score: 97.5

Operações com String seguras para valores nulos

Muitas operações de String lançam NPE se a string for nula. Use padrões defensivos ou String.valueOf() para tratar valores nulos com segurança.

String value = null;

// Null-safe length check
int len = (value != null) ? value.length() : 0;
System.out.println(len); // 0

// Null-safe comparison (put constant first)
boolean isAdmin = "admin".equals(value); // false, no NPE

// String.valueOf converts null to "null" string
System.out.println(String.valueOf(value)); // "null"
System.out.println(Objects.toString(value, "default")); // "default"

Verificação rápida

O que o código a seguir imprime?

String a = "hello";
String b = new String("hello");
System.out.println(a.equals(b));
System.out.println(a == b);

Recapitulação: imutabilidade de String e o pool de strings

Principais conclusões:

  • As strings são imutáveis — as operações retornam novos objetos String e nunca modificam o original
  • Os literais de string são armazenados em pool — dois literais com o mesmo conteúdo compartilham um objeto
  • Use sempre .equals() para comparar o conteúdo de uma String; == compara referências de objetos
  • Use equalsIgnoreCase() para comparações que ignoram maiúsculas e minúsculas
  • A concatenação de strings em laços resulta em O(n²) — use StringBuilder para obter eficiência
  • As strings armazenam o hashCode em cache, tornando-as eficientes e seguras como chaves de HashMap

Perguntas Frequentes

A aula “Imutabilidade de String e o Pool de Strings” é grátis?

Sim — o texto completo de “Imutabilidade de String e o Pool de Strings” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.

O que vou aprender em “Imutabilidade de String e o Pool de Strings”?

Compreenda por que as Strings são imutáveis, como funciona o pool de strings e quando usar == em vez de equals. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Java Academy?

Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.

Quanto tempo leva a aula “Imutabilidade de String e o Pool de Strings”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Java Academy?

Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Imutabilidade de String e o Pool de Strings
  2. StringBuilder para Concatenação Eficiente
  3. Blocos de Texto e String.format
  4. Expressões Regulares com Pattern e Matcher
← Voltar para Java Academy