Java Text Blocks Java 15+
Escrever um texto de várias linhas com aspas comuns é sofrido: um \n no fim de cada linha, um + no começo da próxima, uma barra antes de cada aspa. O text block ("bloco de texto") resolve isso: você abre com três aspas, escreve o texto do jeito que ele deve sair, e fecha com três aspas.
- Como escrever um text block com
"""e as regras de abertura e fechamento. - Como o Java decide quanto da indentação é "margem" do código e quanto é parte do texto.
- Como controlar a quebra no fim: o
"""na linha de baixo ou colado no texto. - A barra
\no fim da linha (juntar linhas) e o\s(manter um espaço). - Como preencher um text block com valores usando
formatted(), com exemplos de JSON e HTML.
Text blocks existem desde o Java 15 (2020). Em projetos presos ao Java 8 ou 11, a alternativa é a concatenação com \n, que você vai ver logo abaixo para comparar.
Antes e depois
A Ana quer guardar uma quadrinha numa variável. Com o que você aprendeu em Concatenação e Caracteres Especiais, seria assim (variável antigo). Com um text block, assim (variável novo):
public class Main {
public static void main(String[] args) {
String antigo = "Batatinha quando nasce\n"
+ "espalha a rama pelo chão\n"
+ "menininha quando dorme\n"
+ "põe a mão no coração\n";
String novo = """
Batatinha quando nasce
espalha a rama pelo chão
menininha quando dorme
põe a mão no coração
""";
System.out.print(novo);
System.out.println(antigo.equals(novo));
}
}
$ java Main.java Batatinha quando nasce espalha a rama pelo chão menininha quando dorme põe a mão no coração true « as duas Strings são idênticas
O equals deu true: o text block é só outro jeito de escrever uma String. Depois de compilado, não há diferença nenhuma; todos os métodos de Métodos de String funcionam igual.
- """
- Três aspas duplas abrem o bloco. Depois delas, nada na mesma linha: o texto começa na linha de baixo.
- Batatinha quando nasce …
- O conteúdo, escrito como deve aparecer. Cada Enter vira um
\n. - """; (na última linha)
- Três aspas fecham o bloco. Como estão na linha de baixo, a última linha do texto também termina com
\n. - System.out.print(novo)
- Usamos
print(sem "ln") porque o texto já termina com quebra de linha. Comprintln, apareceria uma linha em branco a mais.
A margem: quanto da indentação fica?
Repare que, no código, as linhas da quadrinha têm 16 espaços na frente (para ficarem alinhadas com o resto do programa), mas na saída não têm nenhum. O Java tirou esses espaços sozinho. Como ele sabe quais espaços tirar?
A regra: o Java olha todas as linhas do bloco, incluindo a linha do """ de fechamento, e acha a que está mais à esquerda. Essa linha define a margem. Os espaços até a margem são da "arrumação do código" (o nome técnico é indentação incidental) e são removidos de todas as linhas. O que passar da margem é parte do texto.
É como uma folha de caderno com a linha vermelha da margem: tudo que está à esquerda dela não conta; o que está à direita, conta, incluindo os recuos.
public class Main {
public static void main(String[] args) {
String a = """
Ana
Bruno
Carla
""";
String b = """
Ana
Bruno
Carla
""";
String c = """
Ana
Bruno
Carla""";
System.out.print(a);
System.out.println("---");
System.out.print(b);
System.out.println("---");
System.out.print(c);
System.out.println("|fim");
}
}
$ java Main.java
Ana
Bruno « os 2 espaços a mais que a margem ficaram
Carla
---
Ana « o """ estava 4 espaços mais à esquerda: a margem recuou
Bruno
Carla
---
Ana
Bruno
Carla|fim « sem quebra no fim: o """ estava colado no texto
| Bloco | Linha mais à esquerda | Resultado |
|---|---|---|
a | Ana, Carla e o """, empatados (16 espaços) | Margem em 16: Ana sem recuo, Bruno com 2 espaços. |
b | O """ de fechamento (12 espaços) | Margem em 12: todas as linhas ganham 4 espaços na frente. |
c | Ana e Carla (16) | Igual ao a, mas sem a quebra de linha final, porque o """ está na mesma linha de Carla. |
Ou seja, a posição do """ de fechamento é o seu "controle": alinhado com o texto, nenhum recuo extra; mais à esquerda, o texto inteiro ganha recuo; colado na última linha, sem quebra no fim.
A conta da margem é feita caractere por caractere: um tab conta como um caractere, igual a um espaço. Se umas linhas forem recuadas com tab e outras com espaços, o resultado fica estranho. Configure o editor para usar só espaços (as IDEs já fazem isso).
Missão: reescreva o cardápio como um text block. A saída deve continuar igual: o título sem recuo e cada item com dois espaços antes do traço.
public class Main {
public static void main(String[] args) {
String cardapio = "Cardápio do dia\n"
+ " - Arroz\n"
+ " - Feijão\n"
+ " - Salada\n";
System.out.print(cardapio);
}
}
public class Main {
public static void main(String[] args) {
String cardapio = """
Cardápio do dia
- Arroz
- Feijão
- Salada
""";
System.out.print(cardapio);
}
}
Barra no fim da linha, \s, aspas e espaços
Dentro de um text block, as sequências de escape continuam funcionando, e há duas novidades:
public class Main {
public static void main(String[] args) {
String uma = """
Esta frase é bem comprida, mas eu quero \
que ela saia numa linha só.
""";
System.out.print(uma);
String espacos = """
nome:
nota:\s
""";
System.out.print(espacos.replace(" ", "·"));
String aspas = """
Ela disse "oi" e 'tchau'.
Três aspas: \"""
Tab:\tfim
""";
System.out.print(aspas);
}
}
$ java Main.java Esta frase é bem comprida, mas eu quero que ela saia numa linha só. nome: « os 3 espaços do fim da linha sumiram nota:· « o \s virou um espaço (trocado por · para ficar visível) Ela disse "oi" e 'tchau'. Três aspas: """ Tab: fim
- \ (no fim da linha)
- Uma barra como último caractere da linha "cancela" a quebra: a linha de baixo continua na mesma linha do texto. Útil para frases longas que você quer quebrar só no código. Java 15+
- espaços no fim da linha
- O Java remove os espaços que sobram no fim de cada linha (muitos editores os deixam sem você perceber). A linha
nome:virounome:. - \s
- Um espaço que não é removido (space). Use no fim da linha quando o espaço importa. Java 15+
- "oi" e 'tchau'
- Aspas simples e duplas não precisam de barra: o bloco só termina em três aspas seguidas.
- \"""
- Para ter três aspas dentro do texto, escape a primeira.
- \t
- Os escapes comuns (
\t,\n,\\…) funcionam como nas Strings normais.
Preencher com valores: formatted()
Text blocks são ótimos como modelos: um texto fixo com "buracos" a preencher. Os buracos são marcados com %s (um texto), %d (um número inteiro) ou %.1f (um decimal com 1 casa), e o método formatted(…) preenche na ordem. Essas marcações são as mesmas do printf, que tem aula própria em Formatar Texto.
Exemplo: JSON
JSON é um formato de texto muito usado para trocar dados entre programas (por exemplo, entre um site e um servidor). Ele usa muitas aspas duplas, e é aí que o text block brilha: nenhuma barra.
public class Main {
public static void main(String[] args) {
String nome = "Ana";
int idade = 30;
double nota = 9.5;
String json = """
{
"nome": "%s",
"idade": %d,
"nota": %.1f
}
""".formatted(nome, idade, nota);
System.out.print(json);
String certo = """
{"nome": "%s", "nota": %s}
""".formatted(nome, nota);
System.out.print(certo);
}
}
$ java Main.java
{
"nome": "Ana",
"idade": 30,
"nota": 9,5 « vírgula! JSON exige ponto
}
{"nome": "Ana", "nota": 9.5}
- """…""".formatted(nome, idade, nota)
- O text block é uma String, então dá para chamar
formatteddireto no"""de fechamento.nomeentra no%s,idadeno%denotano%.1f. - 9,5
- Uma surpresa real: o computador da Ana está em português (
pt_BR), e o%.1fsegue o costume do país, com vírgula decimal. Para gente, ótimo; para JSON, errado. - "nota": %s
- Com
%s, o número vira texto do jeito do Java (o mesmo doprintln), sempre com ponto:9.5. Outra saída é fixar o idioma, assunto de Formatar Texto.
Exemplo: HTML
HTML, a linguagem das páginas web, também é cheio de aspas e de recuos. Com text block, o código Java fica com a mesma cara da página:
public class Main {
public static void main(String[] args) {
String titulo = "Frutas da feira";
String fruta1 = "maçã";
String fruta2 = "banana";
String html = """
<html>
<body>
<h1>%s</h1>
<ul class="lista">
<li>%s</li>
<li>%s</li>
</ul>
</body>
</html>
""".formatted(titulo, fruta1, fruta2);
System.out.print(html);
}
}
$ java Main.java
<html>
<body>
<h1>Frutas da feira</h1>
<ul class="lista">
<li>maçã</li>
<li>banana</li>
</ul>
</body>
</html>
Os recuos internos (2, 4, 6 espaços além da margem) foram preservados, e as aspas de class="lista" entraram sem barra nenhuma.
Text block ou String comum?
| Situação | Use |
|---|---|
| Texto curto, uma linha | String comum: "Olá, Ana" |
| Texto de várias linhas (mensagens, menus, poemas) | Text block |
| Texto com muitas aspas (JSON, HTML, SQL) | Text block |
| Modelo a ser preenchido | Text block + formatted() |
| Frase longa que deve sair numa linha só | Text block com \ no fim das linhas, ou concatenação com + |
| Projeto em Java 8 ou 11 | Concatenação com \n (text blocks não existem lá) |
Como o resultado é uma String comum, dá para usar todos os métodos nele:
public class Main {
public static void main(String[] args) {
String lista = """
maçã
banana
uva
""";
System.out.println(lista.length());
System.out.println(lista.lines().count());
System.out.println(lista.contains("banana"));
}
}
$ java Main.java 16 « 4 + 6 + 3 letras e 3 quebras de linha 3 « lines() separa o texto em linhas true
Brinque com o código: mude a posição do """ de fechamento (mais para a esquerda, colado na última linha) e acrescente recuos em algumas linhas. Veja como a saída muda.
public class Main {
public static void main(String[] args) {
String menu = """
1. Novo jogo
2. Continuar
2.1 Último salvo
3. Sair
""";
System.out.print(menu);
}
}
Quando dá errado
error: illegal text block open delimiter sequence, missing line terminator
Este código tem um erro de propósito.
public class Main {
public static void main(String[] args) {
String texto = """Olá""";
System.out.println(texto);
}
}
$ javac Main.java
Main.java:3: error: illegal text block open delimiter sequence, missing line terminator
String texto = """Olá""";
^
Main.java:3: error: illegal text block open delimiter sequence, missing line terminator
String texto = """Olá""";
^
2 errors
O que aconteceu: depois do """ de abertura tem de vir uma quebra de linha ("sequência de abertura de text block ilegal, falta o fim de linha"). Text block não serve para texto de uma linha só, nem pode começar na mesma linha das aspas.
Como resolver: para uma linha, use aspas comuns: "Olá". Para várias, passe o texto para a linha de baixo do """.
error: unclosed text block
Este código tem um erro de propósito.
public class Main {
public static void main(String[] args) {
String texto = """
Olá, mundo
;
System.out.println(texto);
}
}
$ javac Main.java
Main.java:3: error: unclosed text block
String texto = """
^
1 error
O que aconteceu: faltou o """ de fechamento ("text block não fechado"). O javac leu o resto do arquivo inteiro como texto e chegou ao fim sem achar as três aspas. O ^ aponta onde o bloco abriu.
Como resolver: feche com """;.
O que aconteceu: o text block terminava com quebra de linha (o """ estava na linha de baixo) e foi impresso com println, que acrescenta outra.
Como resolver: use print, ou cole o """ no fim da última linha.
O que aconteceu: o """ de fechamento ficou mais à esquerda que o texto, e a margem foi calculada a partir dele.
Como resolver: alinhe o """ de fechamento com a primeira coluna do texto.
O que aconteceu: %f/%.1f no formatted seguem o idioma do sistema; em pt_BR, a vírgula.
Como resolver: use %s para o número, ou formate com um idioma fixo (veja Formatar Texto).
Referência
| Escrita | Efeito |
|---|---|
""" + quebra de linha | Abre o bloco (o texto começa na linha seguinte) |
""" sozinho na última linha | Fecha; o texto termina com \n; a posição dele entra no cálculo da margem |
texto""" | Fecha sem \n no fim |
\ no fim da linha | Junta com a linha de baixo (sem quebra) |
\s | Um espaço que não é removido |
\""" | Três aspas dentro do texto |
"""…""".formatted(a, b) | Preenche os %s, %d… do modelo |
texto.lines() | As linhas do texto, uma a uma |
texto.stripIndent() | Aplica a mesma regra de margem a uma String qualquer |
Exercícios
Missão final: monte o JSON de um pedido com um text block e formatted, usando as variáveis. A saída deve ter quatro linhas: {, depois "produto": "Café", e "quantidade": 2 (as duas com 2 espaços de recuo) e por fim }.
public class Main {
public static void main(String[] args) {
String produto = "Café";
int quantidade = 2;
// crie o text block e mostre com System.out.print
}
}
public class Main {
public static void main(String[] args) {
String produto = "Café";
int quantidade = 2;
String pedido = """
{
"produto": "%s",
"quantidade": %d
}
""".formatted(produto, quantidade);
System.out.print(pedido);
}
}
1. Abrir o bloco
Quantas aspas duplas abrem um text block?
2. Um espaço que fica
Qual escape mantém um espaço no fim de uma linha do text block?
3. O que define a margem (os espaços que são removidos) de um text block?
4. O text block abaixo termina com quebra de linha?
String s = """
oi
tchau""";
5. Um text block com a linha Ana e o """ de fechamento na linha de baixo é comparado com equals à String "Ana\n". O resultado é…
Resumo
- Text block:
""", quebra de linha, o texto,""". Existe desde o Java 15 e resulta numa String comum. - A margem é a linha mais à esquerda (incluindo o
"""de fechamento); o que passa dela vira recuo no texto. """na linha de baixo = termina com\n; colado na última linha = sem\n.- Espaços no fim das linhas são removidos;
\smantém um.\no fim da linha junta com a próxima. - Aspas não precisam de barra; só
\""". formatted()transforma o text block num modelo; cuidado com%fe a vírgula dopt_BR.