String Literals and Constant Values
Text blocks provide a readable Java 17 syntax for multiline strings.
Why Multiline Strings Need a Layout Rule
Many programs need a value that spans several lines, such as a short poem, a block of help text, or a snippet of SQL or JSON. In Java, a multiline value written with ordinary string literals becomes a series of quoted fragments joined together, which is hard to read because the layout of the text is lost in the quotation marks and escape characters. Java 17 introduced text blocks as a readable syntax for multiline strings. A text block still produces a String value, so it can be used anywhere a normal string literal is accepted.
A text block can look at first glance like an ordinary string literal that has simply been given extra quotation marks. That impression is the source of the most common mistake, so this article works through the exact rules. The key idea is that a text block has a stricter layout than a normal literal, and the layout decides what ends up in the final string.
What do you think happens?
When you write a text block, does the string value begin with a newline character?
Reveal answer
No, the line break after the opening delimiter is excluded
The newline that follows the opening three double quotes is not part of the string value. The text begins with the first line of content after that newline.
Where the Delimiters Sit
A text block is bounded by two delimiters, each made of three double quotation marks. The opening delimiter comes first and marks where the text begins. The closing delimiter marks where the text block stops. Everything between them, from the line after the opening delimiter down to the line containing the closing delimiter, forms the source of the string value.
A text block is a multiline String literal in Java 17 that begins with an opening delimiter of three double quotation marks, followed only by optional spaces or tabs and a newline, and ends at a closing delimiter of three double quotation marks.
- The opening delimiter is followed only by a newline, so the first line of content starts on the next source line.
- The closing delimiter sits on its own line, which tells Java where the text stops.
- The text is assigned to a String variable, so it is a normal String value afterwards.
The text block is still a single String value. The multiple source lines are a way of writing the value, not a sign that several strings are being created.
How Leading Whitespace Is Stripped
Source code is usually indented so that it lines up with the structure of the program. Java removes common leading whitespace from text-block lines, which lets the source be indented neatly without that indentation automatically appearing in the value. The whitespace removed is the common leading whitespace shared by the lines. Whitespace that is not shared by every line is not removed in the same way, so the relative indentation among the lines of the text is kept.
The position of the closing delimiter matters to this rule. When the closing delimiter sits on its own line, its indentation counts as part of the common leading whitespace that is measured. Moving the closing delimiter changes how much whitespace is stripped, and so it changes the value that the text block produces. The following pair of versions shows the effect of this single change.
String poem = """
Roses are red,
Violets are blue.
""";The closing delimiter is indented four spaces, the same as the text. The common leading whitespace is four spaces, so all four are stripped and the lines start at column zero in the value.
String poem = """
Roses are red,
Violets are blue.
""";The closing delimiter starts at column zero. The common leading whitespace is now zero, so no indentation is stripped and the four spaces before each text line remain in the value.
Finding the Value of an Indented Text Block
A text block has two content lines, Hello and World, each indented eight spaces in the source. The closing delimiter is also indented eight spaces on its own line. What is the string value?
- 1Ignore the opening line
The opening delimiter is followed only by a newline, so that newline is excluded and the value starts at the first content line.
- 2Measure the common indentation
Every content line and the closing delimiter line has eight leading spaces, so the common leading whitespace is eight spaces.
- 3Strip the common indentation
Those eight spaces are removed from each line, which leaves Hello and World starting at the beginning of their lines.
- 4Keep the line breaks between and after lines
A line break separates Hello from World, and the closing delimiter line contributes a final line break at the end of the value.
The value is the text Hello, a line break, World, and a final line break. Written as an escaped literal, it is Hello then backslash n then World then backslash n.
The Opening Line Must Stay Empty
The opening delimiter must be followed only by optional spaces or tabs and then a newline. Text placed after the opening three double quotes on the same line is not allowed. Java 17 applies this stricter layout rule, so a line such as the one below is rejected by the compiler rather than being read as a text block.
- Content follows the opening delimiter on the same line, which breaks the layout rule.
- This is shown only to illustrate the rejected form. It is not a valid text block.
Text Blocks Compared With Concatenation
The main benefit of a text block is in how the value is written and read. A multiline passage can be laid out across several source lines instead of being forced into the less readable form of an ordinary string literal. The result is still a string value, so the surrounding code can use it where a normal string literal is accepted.
| Aspect | Text block | Ordinary literals with concatenation |
|---|---|---|
| Layout in source | Lines of text appear as they will read, between delimiters | Each line is a separate quoted fragment with explicit break characters |
| Line breaks | Taken from the source lines, with the opening newline excluded | Written by hand as escape sequences in each fragment |
| Indentation | Common leading whitespace is stripped, so source indentation does not automatically appear in the value | Indentation appears only if it is typed inside the quotes |
| Result type | A String value | A String value |
Writing the same multiline text in two ways. Both produce String values.
- Each line is an ordinary string fragment joined with the plus operator.
- The line breaks must be written by hand as escape sequences.
Mistakes Beginners Make With Text Blocks
Common mistake Putting the first line of text on the same line as the opening delimiter
What it looks likeString s = """HelloWhy it failsJava 17 requires the opening delimiter to be followed only by optional spaces or tabs and then a newline.
Do this insteadMove the text to the next line, so the opening line holds nothing but the delimiter.
Common mistake Expecting the opening newline to appear in the value
What it looks likeA value expected to start with a line break
Why it failsThe newline after the opening delimiter is excluded from the string value.
Do this insteadIf a leading line break is needed, add it explicitly, for example with an escape sequence at the start of the text.
Common mistake Assuming source indentation is kept in the value
What it looks likeIndented content lines expected to keep their indentation
Why it failsJava removes common leading whitespace from text-block lines, so the indentation shared by the lines is stripped.
Do this insteadCheck where the closing delimiter sits, because it affects how much whitespace is measured and stripped.
Common mistake Forgetting that a closing delimiter on its own line adds a final line break to the value
Practice Reading a Text Block
Consider this text block where the closing delimiter is indented four spaces and the content lines are indented four spaces. Before running any code, work out which whitespace is stripped and whether the value begins with a newline. Then describe how the value would change if the closing delimiter were moved to column zero.
Hints
- The newline after the opening delimiter is never part of the value.
- Compare the indentation of every content line and the closing delimiter line to find the common leading whitespace.
- Moving the closing delimiter to column zero means no common indentation is stripped.
Key Takeaways
- A Java 17 text block begins with an opening delimiter of three double quotes that may be followed only by optional spaces or tabs and a newline, and it ends at a closing delimiter of three double quotes.
- The newline after the opening delimiter is excluded from the string value, so the text starts with the first content line.
- Java removes common leading whitespace from text-block lines, so source indentation can be used for readability without automatically appearing in the value.
- Content cannot appear on the same line as the opening delimiter, and a text block still produces an ordinary String value that is easier to read than concatenated literals.