String como objeto imutável
Em Java, String é um objeto que representa texto e é imutável: depois de criada, seu conteúdo não pode ser alterado. Quando você “muda” uma String, na verdade cria uma nova String e a variável passa a referenciar o novo objeto.
String s = "Java"; s = s + "!"; // cria um novo objeto "Java!"; o "Java" original permanece igualEssa característica traz benefícios (segurança, previsibilidade, uso eficiente de memória em alguns cenários), mas também implica custo quando há muitas concatenações, especialmente em laços.
Imutabilidade na prática: o que acontece ao “alterar”
Considere uma limpeza de entrada:
String entrada = " Ana "; String limpa = entrada.trim(); // "Ana" (novo objeto) // entrada continua " Ana "O método trim() não altera entrada; ele devolve outra String.
Comparação correta de Strings
Para comparar conteúdo de Strings, use equals (ou equalsIgnoreCase quando a diferença entre maiúsculas/minúsculas não importar). Evite usar == para comparar texto, pois == compara referências (se é o mesmo objeto), não o conteúdo.
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
equals
String a = "java"; String b = "java"; boolean mesmoConteudo = a.equals(b); // trueequalsIgnoreCase
String comando = "SAIR"; if (comando.equalsIgnoreCase("sair")) { // ... }Comparação segura contra null
Se há chance de a variável ser null, prefira chamar equals a partir de uma constante conhecida:
String status = null; boolean ok = "OK".equals(status); // false, sem NullPointerExceptionMétodos comuns para manipulação de texto
substring: recortar parte do texto
substring(inicio, fim) devolve uma nova String com caracteres do índice inicio (inclusivo) até fim (exclusivo). substring(inicio) vai até o final.
String cpf = "123.456.789-00"; String parte = cpf.substring(0, 3); // "123" String sufixo = cpf.substring(12); // "00"Passo a passo prático (extraindo DDD de telefone):
- 1) Garanta um formato esperado (ex.:
(11) 99999-0000). - 2) Encontre os índices dos parênteses.
- 3) Use
substringpara recortar.
String tel = "(11) 99999-0000"; int abre = tel.indexOf('('); int fecha = tel.indexOf(')'); String ddd = tel.substring(abre + 1, fecha); // "11"indexOf: localizar caracteres ou trechos
indexOf retorna a posição da primeira ocorrência (ou -1 se não encontrar). Há variações com caractere, String e índice inicial.
String email = "ana.silva@empresa.com"; int arroba = email.indexOf('@'); // 9 String dominio = email.substring(arroba + 1); // "empresa.com"Passo a passo prático (validando presença de separador):
- 1) Procure o separador com
indexOf. - 2) Se retornar
-1, trate como formato inválido. - 3) Caso exista, recorte as partes com
substring.
String linha = "produto=Teclado"; int pos = linha.indexOf('='); if (pos == -1) { throw new IllegalArgumentException("Linha inválida: " + linha); } String chave = linha.substring(0, pos); String valor = linha.substring(pos + 1);split: quebrar texto em partes
split divide a String usando uma expressão regular. Para separadores simples como vírgula, funciona bem; para caracteres especiais de regex (como ., |, ?), é preciso escapar.
String csv = "Ana,Bruno,Caio"; String[] nomes = csv.split(","); // ["Ana", "Bruno", "Caio"]Exemplo com ponto (precisa escapar):
String versao = "1.2.15"; String[] partes = versao.split("\\."); // ["1", "2", "15"]Cuidados comuns:
- Espaços ao redor: combine com
trim()em cada parte. - Campos vazios: dependendo do caso, pode ser necessário tratar resultados vazios.
trim: remover espaços nas extremidades
trim() remove espaços (e alguns caracteres de controle) do início e do fim. É essencial para limpar entradas de usuário e dados vindos de arquivos.
String bruto = " admin "; String usuario = bruto.trim(); // "admin"Passo a passo prático (limpeza de lista separada por vírgula):
String entrada = " Ana , Bruno, Caio "; String[] itens = entrada.split(","); for (int i = 0; i < itens.length; i++) { itens[i] = itens[i].trim(); } // itens: ["Ana", "Bruno", "Caio"]Formatação de texto com String.format
String.format cria Strings formatadas com placeholders. É útil para mensagens padronizadas, relatórios simples e logs legíveis.
Placeholders comuns
%s: texto%d: inteiro%.2f: decimal com 2 casas%n: quebra de linha independente do sistema (use quando precisar de múltiplas linhas)
String nome = "Ana"; int itens = 3; double total = 59.9; String msg = String.format("Olá, %s! Você tem %d itens. Total: R$ %.2f", nome, itens, total);Passo a passo prático (mensagem de cobrança):
- 1) Tenha os dados já em tipos corretos (ex.:
int,double). - 2) Defina o template com placeholders.
- 3) Gere a mensagem com
String.format.
int numeroPedido = 1024; String cliente = "Bruno"; double valor = 120.0; String texto = String.format("Pedido #%d | Cliente: %s | Valor: R$ %.2f", numeroPedido, cliente, valor);Concatenação e custo em laços: por que StringBuilder existe
Como String é imutável, cada concatenação pode criar um novo objeto. Em laços, isso pode gerar muitas alocações e cópias de caracteres, aumentando tempo e uso de memória.
Exemplo de concatenação repetida (evitar em laços grandes)
String resultado = ""; for (int i = 1; i <= 5; i++) { resultado = resultado + i + ","; } // cria várias Strings intermediáriasStringBuilder: concatenação eficiente
StringBuilder é um objeto mutável para montar texto. Você adiciona partes com append e, ao final, chama toString() para obter uma String.
StringBuilder sb = new StringBuilder(); for (int i = 1; i <= 5; i++) { sb.append(i).append(','); } String resultado = sb.toString();Passo a passo prático (gerar lista com separador sem vírgula final):
- 1) Crie um
StringBuilder. - 2) Para cada item, adicione o separador apenas se não for o primeiro.
- 3) Converta para
Stringno final.
String[] nomes = {"Ana", "Bruno", "Caio"}; StringBuilder sb = new StringBuilder(); for (int i = 0; i < nomes.length; i++) { if (i > 0) sb.append(" | "); sb.append(nomes[i]); } String saida = sb.toString(); // "Ana | Bruno | Caio"Exercícios práticos (parsing, limpeza e mensagens formatadas)
1) Parsing de linha chave=valor
Objetivo: Dada uma linha como "produto=Teclado", extrair chave e valor, removendo espaços extras.
Requisitos: usar indexOf, substring e trim.
// Entrada: " produto = Teclado Mecânico " // Saída esperada: chave="produto", valor="Teclado Mecânico"Dicas:
- Use
indexOf('=')e valide-1. - Recorte com
substringe apliquetrim()em ambos.
2) Limpeza de lista de e-mails separados por ponto e vírgula
Objetivo: Transformar " ana@x.com ; BRUNO@y.com; caio@z.com " em uma lista normalizada (sem espaços e com domínio/usuário preservados), e contar quantos são do domínio y.com ignorando maiúsculas/minúsculas.
Requisitos: usar split, trim, equalsIgnoreCase, indexOf e substring.
// Sugestão de passos: // 1) split(";") // 2) trim() em cada item // 3) pegar domínio: substring(email.indexOf('@') + 1) // 4) comparar domínio com equalsIgnoreCase("y.com")3) Gerar mensagem formatada a partir de dados CSV
Objetivo: Dada uma linha CSV "Ana,3,59.90" (nome, quantidade, total), gerar: "Cliente: Ana | Itens: 3 | Total: R$ 59.90".
Requisitos: usar split, trim e String.format.
// Entrada: "Ana,3,59.90" // Saída: "Cliente: Ana | Itens: 3 | Total: R$ 59.90"Dicas:
- Após
split, apliquetrim()nos campos. - Converta quantidade para inteiro e total para decimal conforme sua necessidade.
- Use
String.format("Cliente: %s | Itens: %d | Total: R$ %.2f", ...).
4) Montar relatório com StringBuilder
Objetivo: A partir de um array de linhas "nome: Ana", "nome: Bruno", gerar um relatório com numeração, usando StringBuilder para eficiência.
Requisitos: usar StringBuilder, append, indexOf e substring.
// Entradas: ["nome: Ana", "nome: Bruno"] // Saída: "1) Ana\n2) Bruno\n" (use %n se optar por String.format)Dicas:
- Encontre o
:comindexOfe recorte o valor comsubstring(pos + 1).trim(). - Use
sb.append(i + 1).append(") ").append(nome).append(System.lineSeparator());.