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); // HELLOO 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"); // printsintern(): 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 stringsComportamento 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); // abcdComparando 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")); // 42String é 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.5Operaçõ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
- Imutabilidade de String e o Pool de Strings
- StringBuilder para Concatenação Eficiente
- Blocos de Texto e String.format
- Expressões Regulares com Pattern e Matcher