Text Blocks
Working with multiline strings in Java used to mean a wall of quotes, + operators, and \n escape sequences. Text Blocks, standardized in Java 15, let you write a multiline string naturally — just like you would type it in a text editor — and the compiler handles the rest.
The Problem Text Blocks Solve
Before text blocks, embedding a JSON payload or an HTML snippet in Java code looked like this:
// Old way — hard to read and easy to mis-escape
String json = "{\n" +
" \"name\": \"Alice\",\n" +
" \"age\": 30\n" +
"}";
System.out.println(json);
Output:
{
"name": "Alice",
"age": 30
}
It works, but it is painful to write, painful to read, and even more painful to maintain. Text Blocks fix this entirely.
Your First Text Block
A text block opens with """ followed immediately by a newline, contains the content on the next lines, and closes with """:
public class Main {
public static void main(String[] args) {
String json = """
{
"name": "Alice",
"age": 30
}
""";
System.out.println(json);
}
}
Output:
{
"name": "Alice",
"age": 30
}
The result is exactly the same string — no manual \n, no + concatenation, and no escaped quotes. The compiler strips the leading indentation automatically.
Note: The opening
"""must be followed by a newline. Putting content on the same line as the opening"""is a compile error.
Indentation Stripping — How It Works
Java figures out how many leading spaces to strip by looking at the position of the closing """. Specifically, it removes the common leading whitespace shared by all content lines and the closing delimiter line.
public class Main {
public static void main(String[] args) {
// Closing """ is at column 8 (8 spaces indent)
String sql = """
SELECT id, name
FROM users
WHERE active = true
""";
System.out.println(sql);
}
}
Output:
SELECT id, name
FROM users
WHERE active = true
The indentation you use inside the text block to align with your code is stripped away — leaving the “logical” content cleanly.
Tip: Move the closing
"""to the left to include more leading whitespace in the final string, or further right to strip more. This gives you precise control.
If you want a trailing newline, leave the closing """ on its own line. If you do not want a trailing newline, put the closing """ at the end of the last content line:
String noTrailingNewline = """
hello""";
// "hello" — no newline at the end
Text Blocks with HTML
Text blocks shine when you embed structured content directly in code:
public class Main {
public static void main(String[] args) {
String html = """
<html>
<body>
<p>Hello, <strong>World</strong>!</p>
</body>
</html>
""";
System.out.println(html);
}
}
Output:
<html>
<body>
<p>Hello, <strong>World</strong>!</p>
</body>
</html>
No escaping needed — double quotes inside the content are perfectly fine.
Escape Sequences Still Work
Standard escape sequences like \n, \t, and \\ still work inside text blocks. Java 15 also added two new escape sequences specifically for text blocks:
| Escape | Meaning |
|---|---|
\<line-terminator> | Suppress the newline at that point (join lines) |
\s | Explicit space — prevents trailing whitespace trimming |
Suppressing Newlines with \
public class Main {
public static void main(String[] args) {
String oneLiner = """
This is all \
one line.\
""";
System.out.println(oneLiner);
}
}
Output:
This is all one line.
The \ at the end of a line inside a text block tells the compiler to remove that newline, joining the two lines together.
Preserving Trailing Spaces with \s
Java strips trailing whitespace from each line inside a text block. If you genuinely need trailing spaces (for example, fixed-width columnar output), use \s to anchor the end of the line:
public class Main {
public static void main(String[] args) {
String padded = """
red \s
green\s
blue \s
""";
// Each line ends with exactly one space (the \s)
System.out.print(padded);
}
}
Interpolation-Style Formatting with formatted()
Text blocks are still String objects, so you can chain .formatted() (available since Java 15) to substitute values:
public class Main {
public static void main(String[] args) {
String name = "Bob";
int score = 98;
String message = """
Player : %s
Score : %d
Grade : %s
""".formatted(name, score, score >= 90 ? "A" : "B");
System.out.print(message);
}
}
Output:
Player : Bob
Score : 98
Grade : A
Tip:
.formatted()is a concise alternative toString.format(). Both use the same format specifiers from String Methods.
Text Blocks for SQL
SQL queries are one of the most common use cases. Compare the old and new styles side by side:
public class Main {
public static void main(String[] args) {
// Old style
String oldSql =
"SELECT u.id, u.name, o.total\n" +
"FROM users u\n" +
"JOIN orders o ON u.id = o.user_id\n" +
"WHERE o.total > 100\n" +
"ORDER BY o.total DESC";
// Text block — same result, much cleaner
String newSql = """
SELECT u.id, u.name, o.total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.total > 100
ORDER BY o.total DESC""";
System.out.println(oldSql.equals(newSql)); // true
}
}
Output:
true
Both strings are identical at runtime — the text block just makes the source code dramatically more readable.
Escaping Triple Quotes
If your content contains """, you need to escape at least one of the three quotes:
public class Main {
public static void main(String[] args) {
String example = """
He said \"""hello\""" to everyone.
""";
System.out.print(example);
}
}
Output:
He said """hello""" to everyone.
You only need to escape enough to break the sequence — escaping just the first " of each triple is sufficient.
Under the Hood
At the bytecode level, a text block is a regular String constant — there is no new runtime type. The compiler processes it in three steps during compilation:
- Line ending normalization — all line endings (
\r\n,\r,\n) are normalized to\nso that text blocks produce consistent output across operating systems. - Incidental whitespace stripping — the compiler computes the minimum indentation across all non-empty content lines and the closing
"""line, then removes exactly that many leading spaces from every line. This is called the re-indentation algorithm (JEP 355). - Escape sequence interpretation — standard and new (
\,\s) escape sequences are processed last.
The result is stored in the constant pool exactly like any other string literal, so there is zero runtime overhead. Text blocks that have the same content after compilation will be deduplicated in the String Pool just like regular string literals.
You can verify this with javap -c (see javap Tool) — the ldc instruction that loads the string shows the fully processed value, not the raw text block source.
Version History
| Java Version | Text Blocks Status |
|---|---|
| Java 13 | Preview (JEP 355) |
| Java 14 | Second preview (JEP 368) — added \ and \s |
| Java 15 | Standard (JEP 378) |
Note: If you are on Java 13 or 14, compile with
--enable-previewto use text blocks. For production code, use Java 15 or later.
Quick Rules Cheat Sheet
| Rule | Detail |
|---|---|
Opening """ must be followed by a newline | Content starts on the next line |
Closing """ controls indentation stripping | Move it left to keep more leading spaces |
| Trailing whitespace is stripped per line | Use \s to preserve intentional trailing spaces |
\ at end of line joins lines | Useful for long logical lines |
| No runtime overhead | Compiled to a plain String constant |
Works with all String methods | .strip(), .formatted(), .length(), etc. |
Related Topics
- Strings — The foundation of Java string handling — text blocks produce ordinary
Stringobjects. - String Methods — Explore
.formatted(),.strip(),.indent()and the fullStringAPI that works with text block results. - String Pool & intern() — Understand how text block constants are deduplicated in the JVM string pool just like regular literals.
- Switch Expressions — Another modern Java syntax improvement that, paired with text blocks, makes code dramatically more expressive.
- Records — Records and text blocks together eliminate boilerplate for both structure and embedded content.
- Java 15 / Modern Java — See the full picture of what changed from Java 9 through 21 alongside text blocks.