Text Blocks
Reviewed & published by Brayan K
A text block is a multi-line string literal — opened and closed with triple double-quotes — that lets you write JSON, SQL, and HTML naturally, without escaping every newline or gluing lines together with +.
Part of the free Java course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
Before You Start
You should know how ordinary Strings and escape sequences like \n work, and ideally have seen var. Text blocks need Java 15 or newer.
What You'll Learn
- Opening and closing a text block with triple quotes
- How incidental whitespace is stripped automatically
- Why the closing delimiter's position matters
- The \ (line-join) and \s (escaped-space) escapes
- Filling templates with .formatted(...)
- Writing clean JSON, SQL, and HTML literals
The Big Idea — Quote a Whole Page, Not Each Line
💡 Analogy: Writing a multi-line string the old way is like reading a poem aloud and saying "new line" after every single verse — exhausting and easy to get wrong ("a\n" + "b\n" + ...). A text block is like handing someone the printed page: the line breaks are already there. You write the text once, exactly as it should look, between two """ fences.
And because the compiler strips the indentation you used to line the block up with your code, the block looks neatly indented in your source but produces a clean, un-indented string.
1️⃣ Your First Text Block
Open with """ followed by a newline (nothing else may sit on that line), write your content, then close with """. Everything between is the string. The example below produces exactly the same String as the old concatenation-with-\n approach — proven with .equals.
public class Main {
public static void main(String[] args) {
// A text block: open with """ then a newline, close with """.
String html = """
<html>
<body>
<p>Hello, world!</p>
</body>
</html>
""";
System.out.print(html);
System.out.println("--- end ---");
// The old way needed \n and + on every line:
String oldWay = "<html>\n" +
" <body>\n" +
" <p>Hello, world!</p>\n" +
" </body>\n" +
"</html>\n";
System.out.println("Same text? " + html.equals(oldWay));
}
}2️⃣ Incidental Whitespace
The clever part: the compiler scans every content line and the closing """, finds the smallest shared leading indentation, and strips exactly that much from each line. That common, removable part is incidental whitespace; what remains is essential. This is how a block indented to match your code still yields an un-indented string.
In the second example below, moving the closing """ to the far left lowers the shared minimum, so four leading spaces survive on each line.
public class Main {
public static void main(String[] args) {
// Incidental whitespace: the compiler finds the least-indented line
// (here the closing """) and strips that much from every line.
String text = """
line one
line two indented
line three
""";
System.out.println("[" + text + "]");
// Moving the closing """ further left keeps more leading spaces.
String shifted = """
apple
banana
""";
System.out.println("[" + shifted + "]");
}
}3️⃣ The \ and \s Escapes
Two escapes are unique to text blocks. A backslash at the end of a line removes that line's newline, so a long sentence can be wrapped across several source lines yet stay one line in the string. The \s escape is a single space that also blocks the compiler from trimming trailing spaces — useful when trailing spaces actually matter.
"""
abc \ <- line-join: no newline here
def""" -> "abc def"
"""
row\s""" -> "row " (the trailing space is kept)public class Main {
public static void main(String[] args) {
// A trailing backslash joins a line to the next — no newline added.
String oneLine = """
The quick brown \
fox jumps over \
the lazy dog.""";
System.out.println(oneLine);
// \s is an "escaped space" — it preserves trailing spaces that
// would otherwise be stripped, and is exactly one space.
String padded = """
key:value\s
end""";
System.out.println("[" + padded + "]");
// You can still use \n and \" explicitly inside a text block.
String quoted = """
She said \"hi\".
Next line.""";
System.out.println(quoted);
}
}4️⃣ Filling Templates with .formatted()
Java has no ${name}-style interpolation. To drop values into a block, write %s / %d placeholders and call .formatted(args...) on it — a tidy instance shortcut for String.format. This makes text blocks ideal for JSON payloads and SQL queries built from variables.
public class Main {
public static void main(String[] args) {
String name = "Ada";
int age = 36;
// formatted() (or String.format) fills %s / %d placeholders.
String json = """
{
"name": "%s",
"age": %d,
"active": true
}""".formatted(name, age);
System.out.println(json);
// A SQL query reads naturally as a text block.
String sql = """
SELECT id, name
FROM users
WHERE age >= %d
ORDER BY name""".formatted(18);
System.out.println();
System.out.println(sql);
}
}🧠 Quick Recall
Predict the result before opening each answer.
String s = """hi
more""";Answer: No. Content may not start on the opening line — the """ must be followed by a line terminator. Put hi on the next line.
String s = """
ab""";Answer: 2 — just ab. The four leading spaces are incidental (the closing """ sits at column 4 too) and there's no trailing newline because """ follows ab directly.
String a = """
done
""";
String b = """
done""";Answer: a is "done\n" (closing """ on its own line adds a trailing newline); b is "done" with no newline. Delimiter placement controls the trailing newline.
🎯 Your Turn — A formatted report
Produce the exact multi-line report using a single text block and .formatted(...).
public class Main {
public static void main(String[] args) {
String city = "Paris";
int temp = 21;
// YOUR TURN: build this exact report with ONE text block and
// .formatted(...) — no + concatenation.
// Expected output:
// Weather report
// ---------------
// City: Paris
// Temp: 21 C
// String report = """
// ...
// """.formatted(city, temp);
// System.out.println(report);
}
}🧩 Mini-Challenge — Build an HTML list
Loop items into list rows, then wrap them in a <ul> using a text block.
public class Main {
public static void main(String[] args) {
String[] items = {"Milk", "Eggs", "Bread"};
// MINI-CHALLENGE: build an HTML unordered list. Loop the items into
// a StringBuilder of " <li>...</li>\n" lines, then drop that into a
// text block wrapped in <ul> ... </ul> using .formatted(...).
//
// Expected output:
// <ul>
// <li>Milk</li>
// <li>Eggs</li>
// <li>Bread</li>
// </ul>
// StringBuilder lis = new StringBuilder();
// for (String it : items) { ... }
// String html = """
// <ul>
// %s</ul>""".formatted(lis.toString());
// System.out.println(html);
}
}Common Errors
- ❌ Content on the opening line. """text won't compile. Fix: the opening """ must be followed by a newline.
- ❌ Forgetting the trailing-newline rule. A closing """ on its own line adds a \n. Fix: place it after the last character to omit it.
- ❌ Surprised that indentation vanished. That's incidental-whitespace stripping. Fix: move the closing """ left to keep leading spaces.
- ❌ Expecting ${var} interpolation. Java has none. Fix: use %s/%d with .formatted(...).
- ❌ Trailing spaces silently disappear. The compiler trims line-trailing whitespace. Fix: end the line with \s to keep one space.
- ❌ Using text blocks on Java 14 or earlier without preview enabled. Fix: compile with Java 15+ where they're standard.
Pro Tips
- 💡 Indent the block to match your code. The incidental whitespace is stripped, so it stays readable in source and clean in the string.
- 💡 Great for tests and fixtures. Paste real JSON or SQL straight in without escaping a single quote.
- 💡 Use \s sparingly — only when trailing spaces are genuinely meaningful (e.g. fixed-width tables).
- 💡 Combine with .formatted() to turn a block into a reusable template rather than hard-coding values.
📋 Quick Reference
| Concept | Syntax | Note |
|---|---|---|
| Open delimiter | """ + newline | Nothing else on that line |
| Close delimiter | """ | Own line = trailing \n |
| No trailing newline | text""" | Close right after text |
| Indentation | (automatic) | Common leading WS stripped |
| Keep leading spaces | move """ left | Lowers the shared minimum |
| Line join | end line with \ | Suppresses that newline |
| Keep trailing space | \s | One space, not stripped |
| Single quote | " | No escaping needed |
| Insert values | block.formatted(args) | %s, %d placeholders |
| Explicit newline | \n | Still works inside a block |
| Result type | String | No new type involved |
📚 Resources / Keep Learning
- 📘 Oracle: Programmer's Guide to Text Blocks — the authoritative reference.
- 📗 dev.java: Text Blocks — a hands-on tutorial.
- 📙 JEP 378: Text Blocks — the finalizing specification.
🎉 Lesson Complete!
You can now write multi-line strings cleanly with text blocks, you understand how incidental whitespace is stripped, you know the \ and \s escapes, and you can turn a block into a template with .formatted().
Practice quiz
How do you open a text block?
- A single "
- Three double-quotes followed by a line terminator
- Backticks
- Triple single-quotes
Answer: Three double-quotes followed by a line terminator. A text block opens with """ and a newline; content begins on the next line.
In which Java version did text blocks become a standard feature?
- Java 8
- Java 11
- Java 15
- Java 21
Answer: Java 15. Text blocks previewed in 13/14 and became standard in Java 15 (JEP 378).
What is 'incidental' whitespace?
- Trailing spaces only
- The common leading indentation the compiler strips
- Tabs only
- Whitespace inside strings
Answer: The common leading indentation the compiler strips. The compiler finds the minimum indentation across all lines (and the closing delimiter) and removes that much from every line.
What does a trailing backslash \ at the end of a line in a text block do?
- Inserts a literal backslash
- Suppresses the newline, joining the line to the next
- Escapes a quote
- Adds a space
Answer: Suppresses the newline, joining the line to the next. A line-ending \ removes the newline so two source lines become one logical line.
What does \s mean in a text block?
- A tab
- A newline
- A single space that is not stripped
- A null character
Answer: A single space that is not stripped. \s is an escaped space; it is exactly one space and prevents trailing-space stripping.
Where must the content of a text block start?
- On the same line as the opening """
- On the line after the opening """
- Anywhere
- At column 0
Answer: On the line after the opening """. Nothing except whitespace may follow the opening """ on its line; content starts on the next line.
Does the position of the closing """ affect indentation?
- No
- Yes — it participates in determining the common indentation to strip
- Only in Java 21
- Only with \s
Answer: Yes — it participates in determining the common indentation to strip. The closing delimiter's indentation is part of the whitespace calculation, so moving it left keeps more leading spaces.
How do you insert variable values into a text block?
- Use ${var} interpolation
- Text blocks cannot hold variables
- Use .formatted(args) or String.format
- Use + concatenation only
Answer: Use .formatted(args) or String.format. Java has no string interpolation; call .formatted(...) on the block (or String.format) to fill %s/%d placeholders.
Are you required to escape a single " inside a text block?
- Yes, always
- No — a lone double-quote is fine; only three in a row need care
- Only at line start
- Only in JSON
Answer: No — a lone double-quote is fine; only three in a row need care. Single and double quotes need no escaping inside a text block; you only manage sequences of three quotes.
What is the type of a text block expression?
- char[]
- StringBuilder
- String
- TextBlock
Answer: String. A text block is just a String literal written across multiple lines — its type is String.
Continue this course
- Previous: Local Variable Type Inference (var)
- Next: Switch Expressions — Arrow labels, yield, and exhaustive switch that returns a value (Java 14+)
- Quick reference: Java cheat sheet
Frequently asked questions
What exactly is a text block?
A text block is a multi-line String literal that opens with three double-quotes followed by a newline and closes with three double-quotes. Inside it you can write newlines, quotes, and indentation naturally, without or + concatenation on every line. Crucially, the result is just an ordinary String — there is no new TextBlock type. Text blocks previewed in Java 13 and 14 and became a permanent feature in Java 15.
How does indentation work — what is incidental whitespace?
The compiler looks at every content line and at the closing delimiter, finds the smallest amount of leading whitespace they share, and removes exactly that much from every line. That shared, removable indentation is called 'incidental' whitespace; whatever is left is 'essential' and stays in the string. This is why you can indent the whole block to line up with your code, yet the resulting string isn't indented. Moving the closing """ to the left keeps more leading spaces on every line.
What do the \ and \s escapes do?
A backslash at the very end of a content line suppresses the newline that would normally be added there, joining that line to the next — handy for wrapping one long logical line across several source lines. The \s escape inserts a single space and, because it counts as a non-whitespace marker, it also prevents the compiler from stripping trailing spaces on that line. Both escapes are unique to text blocks and solve the otherwise-awkward problems of long lines and meaningful trailing spaces.
Can I put variables inside a text block?
Not directly — Java has no string interpolation, so there is no ${name} syntax. The idiomatic approach is to write %s, %d, and other placeholders in the block and then call .formatted(args...) on it (which is shorthand for String.format). You can also concatenate with + after the block, but .formatted keeps multi-line templates clean and readable.
Do I need to escape quotes inside a text block?
A single double-quote needs no escaping at all, which is the whole point — you can write JSON, HTML, and SQL that contain quotes without a forest of backslashes. You only have to be careful with three or more double-quotes in a row, since """ could be read as the closing delimiter; in that rare case you escape one of them as \". Single quotes never need escaping.