Text Blocks
Text Blocks
Before Java 15 made text blocks a permanent feature, embedding multi-line strings in Java code was painful. JSON bodies, SQL queries, HTML fragments, and XML payloads all had to be written as a tangle of concatenated single-line strings with manual \n and escaped quotes everywhere. Text blocks, introduced as a preview in Java 13 and finalised in Java 15, solve this problem with a clean, readable syntax.
The Old Way vs. The New Way
Here is the same JSON string written both ways:
The second version is what the source file actually looks like — indentation included — without a single escaped quote or newline escape sequence.
Syntax Rules
A text block opens with three double-quotes (""") followed by optional whitespace and then a mandatory newline. The opening """ cannot be immediately followed by content on the same line. The closing """ can either sit on its own line (adding a trailing newline to the value) or follow the last line of content directly (no trailing newline).
""" line is never part of the string content. Its only job is to start the block and anchor the indentation baseline. The content begins on the very next line.
Incidental Whitespace — The Key Concept
The most important thing to understand about text blocks is how Java handles indentation. If you indent a text block eight spaces to match your surrounding code, Java does not blindly include all eight spaces in the string value. Instead, it strips incidental whitespace — the common leading whitespace shared by every content line and the closing """.
The closing """ acts as an indentation anchor. Java looks at the column of the closing delimiter and removes that many leading spaces from every content line.
You can deliberately keep some leading whitespace by positioning the closing """ to the left of the content:
""" with the opening indentation of the text block itself. This produces zero incidental whitespace in the output and makes the intent obvious at a glance.
Escape Sequences and New Additions
All standard Java escape sequences work inside text blocks: \t, \\, \uXXXX, and so on. Because double quotes no longer need escaping inside a text block, you only need to escape a " if it is part of a sequence of three or more consecutive quotes.
Java 14 also introduced two new escape sequences specifically for text blocks:
\<line-terminator>— a backslash at the end of a source line suppresses the newline at that point, letting you split a long logical line across multiple source lines without embedding an actual newline in the string.\s— a single space that is never stripped by incidental-whitespace trimming. Useful to force trailing spaces on a line.
String.formatted() — Interpolation Without a New Operator
Java still has no built-in string interpolation, but text blocks pair naturally with String.formatted() (an instance method added in Java 15 that calls String.format on the receiver):
Practical Example — Embedding HTML
String objects. They are not a new type, they are not lazy, and they are not templates. All string operations — equals(), substring(), replaceAll() — work identically. The compiler processes the incidental whitespace and escape sequences at compile time; at runtime a text block is just a regular String constant.
When to Use Text Blocks
- SQL queries longer than one clause — indentation matches logical structure.
- JSON / XML payloads in tests or configuration code.
- HTML or SVG fragments returned from helper methods.
- Expected output strings in unit tests — comparing against a readable block instead of a single-line blob makes failures easier to diagnose.
- Log message templates with placeholders.
For simple one-liners or dynamically assembled strings, regular string literals and StringBuilder remain perfectly fine.
Summary
Text blocks let you write multi-line strings exactly as they should appear, without escape sequences or concatenation noise. The critical mechanic is incidental whitespace stripping controlled by the column position of the closing """. Pair text blocks with .formatted() for lightweight parameterisation, use \ line continuation to suppress unwanted newlines, and remember that the result is still a plain String — all existing APIs apply unchanged.