W3docs

Formatação de Strings em Java

Formate strings Java com String.format e System.out.printf usando especificadores como %s, %d, %f e %n.

A concatenação (+) funciona bem para strings curtas e simples. No momento em que você quiser fixar um número em um número específico de casas decimais, alinhar colunas com preenchimento, incorporar uma data com layout consistente ou, de outro modo, formatar valores em vez de simplesmente colá-los, você recorre à API no estilo printf que o Java tomou emprestado do C.

Existem três pontos de entrada intimamente relacionados e você verá todos eles em código real:

  • String.format(fmt, args...) — retorna uma String formatada.
  • "...".formatted(args...) — forma de instância adicionada no Java 15. Resultado idêntico, mais amigável para encadeamento.
  • System.out.printf(fmt, args...) — imprime diretamente em um PrintStream (ou qualquer Formatter).

Todos os três compartilham a mesma sintaxe de especificadores de formato. Aprenda uma vez.

Especificadores de formato

Um especificador tem a forma %[flags][width][.precision]conversion. A letra de conversão é o único elemento obrigatório. O restante ajusta largura, alinhamento, preenchimento e precisão.

String s = String.format("%-10s | %5d | %8.2f", "apples", 42, 3.14159);
// "apples     |    42 |     3.14"

As conversões mais úteis:

ConversãoArgumentoSignificado
%squalquertoString() do valor
%dinteirointeiro decimal
%fponto flutuantedecimal de ponto fixo
%eponto flutuantenotação científica
%gponto flutuanteo mais curto entre %e e %f
%x, %ointeirohexadecimal / octal
%ccaracterecaractere único
%bqualquertrue/false (null → "false")
%nnenhumseparador de linha adequado à plataforma
%%nenhumum % literal
%t...data/horatoda uma família — %tF, %tT, etc.

A largura preenche a saída com pelo menos N caracteres; a precisão significa "dígitos decimais" para floats e "máximo de caracteres" para strings.

Flags: alinhamento, sinal, preenchimento com zeros e agrupamento

Um conjunto de flags se encaixa entre % e a largura:

  • - — alinha à esquerda dentro da largura. O padrão é alinhar à direita.
  • 0 — preenche com zeros até a largura (somente para conversões numéricas).
  • + — sempre exibe sinal em números (+42, -7).
  • (espaço) — exibe um espaço à esquerda para números positivos, como +, mas com um espaço em branco.
  • , — agrupa dígitos usando o separador de milhares da localidade.
  • ( — envolve números negativos em parênteses, estilo contábil.
String.format("%08d", 42);        // "00000042"
String.format("%,d", 1234567);    // "1,234,567"
String.format("%+.2f", 3.14159);  // "+3.14"
String.format("%-10s|", "hi");    // "hi        |"

Largura e precisão

A largura é a largura mínima do campo — se o valor formatado for mais largo, nada é truncado.

A precisão tem significados diferentes para conversões distintas:

  • %.3f — três dígitos após a vírgula decimal.
  • %.10s — trunca a string para no máximo 10 caracteres.
  • %.4e — quatro dígitos de precisão de mantissa.

Combinar largura e precisão é comum quando você quer que colunas se alinhem e números sejam arredondados:

String.format("%10.4f", Math.PI);   // "    3.1416"
String.format("%-10.4s", "abcdef"); // "abcd      "

%n vs \n

%n emite o separador de linha adequado à plataforma: "\n" no Unix, "\r\n" no Windows. \n é sempre exatamente um byte. Para arquivos e saídas de protocolo onde a terminação de linha importa com precisão, prefira \n e escolha-a conscientemente. Para saída de console que deve parecer correta em qualquer SO em que a JVM esteja rodando, %n é a escolha mais segura.

Índices de argumento: reutilização e reordenação

Um especificador da forma %N$... se refere ao N-ésimo argumento (baseado em 1). Útil quando um valor aparece mais de uma vez em um modelo, ou quando a ordem natural de leitura difere da ordem dos argumentos:

String.format("%1$s, %1$s, %1$s!", "go");        // "go, go, go!"
String.format("%2$s before %1$s", "lunch", "tea"); // "tea before lunch"

Esta é a ferramenta certa ao localizar modelos — idiomas diferentes colocam substantivos em posições diferentes, e um tradutor pode reorganizar os marcadores de posição sem tocar no local da chamada.

A localidade importa para números e datas

A formatação de números respeita a localidade padrão da JVM, a menos que você a substitua. Em en-US você obtém 3.14; em de-DE você obtém 3,14; em fr-FR os milhares são agrupados com um espaço não separável. Para saída voltada a humanos, isso geralmente é o que você quer. Para formatos de dados — JSON, CSV, arquivos de log, qualquer coisa legível por máquina — é um desastre aguardando uma implantação em Frankfurt.

Sempre passe uma localidade explicitamente para saída legível por máquina:

String json = String.format(Locale.ROOT, "{\"price\": %.2f}", 19.95);
// "{\"price\": 19.95}" — always, regardless of JVM locale

Locale.ROOT significa "sem formatação específica de localidade" — ponto como decimal, sem agrupamento. Locale.US é a outra escolha comum para o mesmo propósito. O perigo está em não passar uma localidade e presumir.

Formatação de data/hora

%t é uma meta-conversão: a letra que a segue escolhe o campo. O mesmo argumento Date, Calendar, Long (millis) ou java.time.temporal.TemporalAccessor pode ser formatado de várias maneiras:

LocalDateTime now = LocalDateTime.of(2026, 5, 29, 14, 30, 15);
String.format("%tF",   now);          // "2026-05-29"  — ISO date
String.format("%tT",   now);          // "14:30:15"    — 24-hour time
String.format("%tA",   now);          // "Friday"      — locale-dependent
String.format("%1$tF %1$tT", now);    // "2026-05-29 14:30:15"

Para qualquer coisa além de formatação rápida, a API java.time.format.DateTimeFormatter é mais flexível e consciente da localidade — mas %tF e seus afins continuam sendo úteis em linhas de log.

Armadilhas comuns

  • Conversão errada para o tipo. String.format("%d", 3.14) lança IllegalFormatConversionException em tempo de execução — %d quer inteiro, %f quer ponto flutuante. O compilador não consegue verificar isso.
  • Argumentos ausentes. Esquecer um argumento de marcador lança MissingFormatArgumentException.
  • Decimal dependente de localidade em saída de máquina. Abordado acima.
  • %s em null. Produz "null". Aceitável para logs, embaraçoso em saída voltada ao usuário.
  • Usar + para números formatados. "Price: " + 19.95"Price: 19.95", mas "Price: " + 0.1 + 0.2"Price: 0.10.2", não "Price: 0.3" — concatenação, não adição.

Um exemplo prático

Um pequeno formatador de resumo de pedidos que exercita largura, precisão, alinhamento, agrupamento, localidade e a conversão de data %t. A saída é um relatório organizado de duas colunas — o tipo de coisa que você construiria manualmente com auxiliares padLeft.

java— editable, runs on the server

Dois pontos a observar: o %<tT na linha "Placed" reutiliza o argumento anterior (< é o flag de referência anterior), evitando um segundo placedAt redundante. E a linha JSON usa Locale.ROOT — o mesmo código em uma JVM alemã ainda emite 1339.43, não 1339,43, que é exatamente o que um analisador JSON espera.

O que vem a seguir

Construir strings é metade do trabalho. Compará-las — igualdade, ordenação, dobramento de maiúsculas/minúsculas, a diferença entre == e equals — é a outra metade e uma fonte frequente de bugs sutis. Continue para Comparação de Strings em Java.

Prática

Prática
Você quer formatar um `double` total como uma string com separador de milhares e exatamente duas casas decimais, e precisa que o resultado use um ponto como separador decimal independentemente da localidade da JVM (para que um consumidor JSON possa analisá-lo). Qual chamada faz isso corretamente?
Você quer formatar um `double` total como uma string com separador de milhares e exatamente duas casas decimais, e precisa que o resultado use um ponto como separador decimal independentemente da localidade da JVM (para que um consumidor JSON possa analisá-lo). Qual chamada faz isso corretamente?
Was this page helpful?