Concepts / String Literals and Constant Values

String Literals and Constant Values

Text blocks provide a readable Java 17 syntax for multiline strings.

  • Programming

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?

  • Yes, the line break after the opening delimiter is kept

  • No, the line break after the opening delimiter is excluded

Reveal answer
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.

Opening delimiterthree double quotesOptional spaces, thennewlineexcluded from the valueContent linesbecome the string textClosing delimiterthree double quotes, marksthe endfollowed bythenends at
Which characters sit between the opening and closing delimiters, and which of them end up in the string value?
Definition

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.

Notes on the code
  • 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.
Key point

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.

Before
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.

After
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.

Roses are red,four leading spaces insourceRoses are red,no leading spaces in valueViolets are blue.four leading spaces insourceViolets are blue.no leading spaces in valueClosing delimiterfour leading spaces insourceFinal newlineclosing line ends the textstrip common fourstrip common foursets the end
How does the four-space indentation of the source lines change when the closing delimiter is indented the same amount as the text?
Worked example

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?

  1. 1
    Ignore 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.

  2. 2
    Measure the common indentation

    Every content line and the closing delimiter line has eight leading spaces, so the common leading whitespace is eight spaces.

  3. 3
    Strip the common indentation

    Those eight spaces are removed from each line, which leaves Hello and World starting at the beginning of their lines.

  4. 4
    Keep 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.

Result

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.

java
Notes on the code
  • 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.

AspectText blockOrdinary literals with concatenation
Layout in sourceLines of text appear as they will read, between delimitersEach line is a separate quoted fragment with explicit break characters
Line breaksTaken from the source lines, with the opening newline excludedWritten by hand as escape sequences in each fragment
IndentationCommon leading whitespace is stripped, so source indentation does not automatically appear in the valueIndentation appears only if it is typed inside the quotes
Result typeA String valueA String value

Writing the same multiline text in two ways. Both produce String values.

java
Notes on the code
  • 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 like
    String s = """Hello
    Why it fails

    Java 17 requires the opening delimiter to be followed only by optional spaces or tabs and then a newline.

    Do this instead

    Move 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 like

    A value expected to start with a line break

    Why it fails

    The newline after the opening delimiter is excluded from the string value.

    Do this instead

    If 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 like

    Indented content lines expected to keep their indentation

    Why it fails

    Java removes common leading whitespace from text-block lines, so the indentation shared by the lines is stripped.

    Do this instead

    Check 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

MEDIUM

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.