Java Text Block
Last modified: July 16, 2026
This Java Text Block tutorial shows how to use text blocks (multi-line
string literals) introduced in Java 13 as a preview feature and standardised
in Java 15 (JEP 378). We cover text block syntax, indentation stripping,
escape sequences, formatting with formatted, and practical
examples.
Text Block
A text block is a multi-line string literal in Java that avoids
the need for explicit line terminators, string concatenation, and escape
sequences for special characters. It is delimited by three double-quote
characters (""") at the opening and closing.
Text blocks significantly improve the readability of multi-line strings such as JSON, XML, HTML, SQL queries, or structured log messages. Instead of writing cumbersome concatenated or escaped strings, a text block preserves the natural formatting of the content.
String html = """
<html>
<body>
<p>Hello, World!</p>
</body>
</html>
""";
The opening delimiter must be followed by a line terminator — the text begins on the next line. The closing delimiter determines the common indentation to be stripped.
Text block syntax
A text block starts with three double-quote characters followed by a line break. The content follows on subsequent lines and ends with another set of three double-quote characters.
void main() {
String text = """
Hello there!
This is a text block.
It spans multiple lines.
""";
System.out.println(text);
}
The text block preserves the line breaks and the indentation of each line. The closing delimiter is placed on its own line to define the common left margin.
$ java Main.java Hello there! This is a text block. It spans multiple lines.
The common leading whitespace shared by all lines (including the closing delimiter line) is automatically removed by the compiler. In the example above, eight spaces of indentation are stripped from each line.
Indentation stripping algorithm
Java applies a three-step algorithm to process text block content:
- Line terminators — all line terminators are normalized to
\n. - Incidental whitespace — the common leading whitespace is determined from all content lines and the closing delimiter line, then removed from each line.
- Trailing whitespace — trailing whitespace on each line is removed.
The amount of whitespace stripped is determined by finding the minimum indentation across all non-blank content lines and the closing delimiter line. This guarantees predictable formatting regardless of the code indentation level.
void main() {
String text = """
{
"name": "John Doe",
"age": 42,
"city": "New York"
}
""";
System.out.println(text);
}
The minimum indentation (eight spaces, based on the closing delimiter line) is stripped from all lines. The JSON data retains its internal indentation.
$ java Main.java
{
"name": "John Doe",
"age": 42,
"city": "New York"
}
Trailing whitespace
Java text blocks automatically remove trailing whitespace from each line.
This prevents accidental whitespace at the end of lines and ensures
consistent formatting. If trailing whitespace is semantically important,
it can be preserved using the \s escape sequence or the
\040 octal escape.
void main() {
String lines = """
Line with trailing space\s
Next line
""";
System.out.println(lines);
}
The \s escape forces a space character that is not trimmed.
Without it, the trailing space before the line break would be removed.
$ java Main.java Line with trailing space Next line
Escape sequences in text blocks
Text blocks support all standard Java escape sequences plus two additional
ones introduced specifically for text blocks: \s (space) and
\<line-terminator> (line continuation).
| Escape | Meaning |
|---|---|
\n |
Newline (U+000A) |
\t |
Tab (U+0009) |
\\ |
Backslash |
\" |
Double quote (inside text block, " is also valid) |
\s |
Space that is not trimmed (text block only) |
\<newline> |
Line continuation — suppresses the line terminator (text block only) |
The line continuation escape allows breaking a long line across multiple source lines without introducing an actual line break in the resulting string.
void main() {
String text = """
Hello, \
there! \
How are you?
""";
System.out.println(text);
}
The backslash followed by a line break suppresses the line terminator, joining the text into a single line.
$ java Main.java Hello, there! How are you?
Using the formatted method
Text blocks work seamlessly with the formatted instance method
(equivalent to String.format) for string interpolation and
formatting. This is the preferred way to inject dynamic values into a
text block.
void main() {
String name = "John";
int age = 42;
String city = "New York";
String msg = """
Name: %s
Age: %d
City: %s
""".formatted(name, age, city);
System.out.println(msg);
}
The formatted method applies String.format style
formatting to the text block. Each %s or %d
placeholder is replaced with the corresponding argument.
$ java Main.java Name: John Age: 42 City: New York
Generating HTML
Text blocks are ideal for generating HTML templates without the need for string concatenation or escaping.
void main() {
String title = "ZetCode";
String heading = "Java Text Blocks";
String content = "Learn about multi-line strings.";
String html = """
<!DOCTYPE html>
<html>
<head>
<title>%s</title>
</head>
<body>
<h1>%s</h1>
<p>%s</p>
</body>
</html>
""".formatted(title, heading, content);
System.out.println(html);
}
The HTML template uses %s placeholders for dynamic values.
The formatted call replaces them at runtime.
$ java Main.java
<!DOCTYPE html>
<html>
<head>
<title>ZetCode</title>
</head>
<body>
<h1>Java Text Blocks</h1>
<p>Learn about multi-line strings.</p>
</body>
</html>
Building SQL queries
Multi-line SQL queries benefit enormously from text blocks. The query structure is preserved and the indentation makes the SQL readable.
void main() {
String table = "employees";
String condition = "salary > 50000";
String query = """
SELECT id, name, department, salary
FROM %s
WHERE %s
ORDER BY salary DESC
""".formatted(table, condition);
System.out.println(query);
}
The SQL query is written in a natural indented format. The table name and
WHERE condition are injected via formatted.
$ java Main.java SELECT id, name, department, salary FROM employees WHERE salary > 50000 ORDER BY salary DESC
Embedding JSON
Text blocks make it easy to embed JSON data directly in source code without escaped quotes or concatenation.
void main() {
String json = """
{
"userId": 1,
"userName": "johndoe",
"email": "john@example.com",
"roles": ["admin", "editor"]
}
""";
System.out.println(json);
// Formatting a JSON template
int id = 2;
String username = "janeb";
String email = "jane@example.com";
String json2 = """
{
"userId": %d,
"userName": "%s",
"email": "%s"
}
""".formatted(id, username, email);
System.out.println(json2);
}
The first text block contains a static JSON structure. The second text block
demonstrates dynamic JSON generation using formatted.
$ java Main.java
{
"userId": 1,
"userName": "johndoe",
"email": "john@example.com",
"roles": ["admin", "editor"]
}
{
"userId": 2,
"userName": "janeb",
"email": "jane@example.com"
}
Indent method
The indent method adjusts the indentation of a text block by
adding or removing leading whitespace from each line. A positive value adds
spaces, a negative value removes spaces.
void main() {
String text = """
first line
second line
third line
""".indent(4);
System.out.println(text);
String text2 = """
deep line
another deep line
""".indent(-4);
System.out.println(text2);
}
indent(4) adds four spaces of indentation to each line.
indent(-4) removes four spaces from each line (if available).
$ java Main.java
first line
second line
third line
deep line
another deep line
Strip indent method
The stripIndent method removes the common leading whitespace
from each line, similar to what the compiler does when parsing a text block.
This is useful for re-indenting strings that were not originally defined as
text blocks.
void main() {
String sql = """
SELECT id, name
FROM users
WHERE active = true
""".stripIndent();
System.out.println(sql);
}
The stripIndent method removes the common indentation (12 spaces
in this case) from all lines, producing a flush-left result.
$ java Main.java SELECT id, name FROM users WHERE active = true
Translate escapes method
The translateEscapes method processes escape sequences in a
string, converting recognised escape sequences (such as \n,
\t) into their actual character equivalents. This is useful
when escape sequences are received as literal text from an external source,
such as a file or a network API, where the compiler has not processed them.
void main() {
// Simulating data read from an external file or API at runtime.
// (In real life, this would be something like
// Files.readString(Path.of("logs.txt")))
// We use \\ here in the source code just to simulate receiving raw text
// with literal backslashes.
String rawLogData = "Timestamp: 10:05\\tStatus: ERROR\\n"
+ "Timestamp: 10:06\\tStatus: RECOVERED";
System.out.println("--- Raw (unformatted) ---");
System.out.println(rawLogData);
System.out.println();
System.out.println("--- With translateEscapes() ---");
System.out.println(rawLogData.translateEscapes());
}
The string contains literal \t and \n characters
— two characters each: a backslash followed by a letter. After calling
translateEscapes, these are converted to actual tab and newline
characters.
$ java Main.java --- Raw (unformatted) --- Timestamp: 10:05\tStatus: ERROR\nTimestamp: 10:06\tStatus: RECOVERED --- With translateEscapes() --- Timestamp: 10:05 Status: ERROR Timestamp: 10:06 Status: RECOVERED
$ java Main.java first line second line third line
Source
Java Text Blocks - Language Reference
In this article, we have worked with Java text blocks.
Author
List all Java tutorials.