Text Blocks

Text blocks (Java 15+) let you write multi-line string literals with triple-quote delimiters, without the escape-sequence and concatenation noise of traditional strings.

A text block, standardized in Java 15 (JEP 378, after previews in 13 and 14), is a multi-line string literal delimited by triple double-quotes ("""). It's designed for embedding readable, multi-line content — HTML, JSON, SQL, formatted text — directly in source code without a wall of \n and + concatenation.

The Problem: Traditional Multi-Line Strings

Before text blocks, embedding multi-line content required explicit \n escapes and string concatenation for every line, or escaping every embedded " character — both hurt readability precisely for the content (structured text) where readability matters most.

// Traditional style
String json = "{\n" +
              "  \"name\": \"Claude\",\n" +
              "  \"role\": \"assistant\"\n" +
              "}";

Basic Syntax: Triple Quotes

A text block starts with """ immediately followed by a line terminator (nothing else may appear on the opening line except optional whitespace) and ends with a closing """. Everything between is the string content, with actual newlines in the source becoming \n in the resulting String — no escaping needed for embedded quotes or newlines.

Embedded double quotes need no escaping at all inside a text block, unlike a traditional string literal.

String json = """
    {
      "name": "Claude",
      "role": "assistant"
    }
    """;
System.out.println(json);
// {
//   "name": "Claude",
//   "role": "assistant"
// }

Result Type: Still java.lang.String

A text block is just a different literal syntax for producing a String — the resulting value is instanceof String, identical in every way (interning, immutability, methods) to a string produced by a traditional double-quoted literal. There is no separate 'text block type.'

String a = "hello";
String b = """
    hello""";
System.out.println(a.equals(b.stripTrailing())); // depends on exact indentation, but both are plain String

Automatic Indentation Handling

The compiler strips a common amount of leading whitespace from every line based on the least-indented non-blank line (this includes the closing """ delimiter's own indentation if it's on its own line, which is exactly why lining up the closing delimiter is a common way to control the block's indentation deliberately). This lets you indent the text block naturally to match your surrounding code without that indentation leaking into the string content.

Moving the closing """ further left (less indented than the content) keeps more leading whitespace in every line; moving it to column 0 keeps the content's original indentation relative to the source almost entirely.

void printGreeting() {
    String msg = """
        Hello,
        World!
        """; // closing delimiter's indentation sets the stripped margin
    System.out.print(msg);
    // Hello,
    // World!
    // (each line has zero leading spaces in the actual String)
}

Trailing Newline Behavior

If the closing """ is on its own line, the text block's value ends with a trailing \n (a line terminator) after the last content line. If the closing """ is placed immediately after the last content instead (same line, no line break before it), there is no trailing newline.

String withTrailingNewline = """
    line1
    line2
    """; // ends with \n after "line2"

String noTrailingNewline = """
    line1
    line2"""; // no trailing \n

Escape Sequences in Text Blocks

Text blocks support the same escape sequences as regular strings (\n, \t, \\, \", unicode escapes, etc.) for the rare case you need one explicitly. Two escapes exist specifically for text blocks: \ at the end of a line suppresses that line's newline (joining it to the next line, useful for a long logical line you want to wrap in source without a literal break in the output), and \s inserts an explicit space that the compiler's automatic trailing-whitespace stripping will not remove.

String joined = """
    This is one \
    long line.
    """;
System.out.println(joined); // This is one long line.

String paddedTable = """
    Name:\s\s\sJava
    Ver:\s\s\s\s17
    """; // \s preserves the trailing/embedded spaces exactly

Trailing Whitespace Is Stripped Per Line

The compiler strips trailing (end-of-line) whitespace from each line of a text block automatically, even whitespace you typed intentionally, to avoid invisible-whitespace bugs from editors/tools trimming or not trimming trailing spaces inconsistently. Use \s at the exact position you need a space preserved if trailing spaces matter to your content.

Embedding Quotes

A single or double " character can appear unescaped inside a text block. Only three consecutive unescaped """ would be ambiguous with the closing delimiter, so that specific sequence needs at least one \" escape; isolated quotes need nothing.

String quote = """
    She said "hello" to the group.
    """; // no escaping needed for isolated double quotes

Practical Use Cases

Text blocks shine anywhere you'd otherwise be assembling multi-line structured text via concatenation: SQL queries, JSON/XML/HTML fragments, help/usage text, multi-line log message templates, or test fixtures with expected multi-line output.

String sql = """
    SELECT id, name
    FROM users
    WHERE active = true
    ORDER BY name
    """;

String html = """
    <html>
      <body>
        <p>Hello, World!</p>
      </body>
    </html>
    """;

Combining With String Methods and formatted()

Since a text block produces a normal String, it supports every String method, including .formatted(...) (Java 15+), a convenient instance-method alternative to String.format(...) for substituting values into a template.

String template = """
    Name: %s
    Age:  %d
    """;
System.out.println(template.formatted("Ann", 30));
// Name: Ann
// Age:  30

Java Version

Text blocks were previewed in Java 13 (JEP 355) and Java 14 (JEP 368), and became a standard, permanent language feature in Java 15 (JEP 378). No preview flags are needed on Java 15+.

Key Takeaways

A text block starts and ends with """; the opening """ must be followed immediately by a line terminator.

A text block produces an ordinary java.lang.String — nothing about its type or behavior differs from a regular string literal.

The compiler auto-strips common leading indentation, based on the least-indented line (including the closing delimiter's position).

\s preserves an intentional space that automatic trailing-whitespace stripping would otherwise remove; a trailing \ joins a line to the next without a newline.

Text blocks became standard in Java 15, after previews in 13 and 14.

String s = """hello"""; // opening """ must be followed by a line terminator - compile error String s = """ hello""";

The syntax requires the opening triple-quote to be immediately followed by a newline — no content is allowed on the same line as the opening delimiter.

String padded = """ Name: Age: """; // trailing spaces after 'Name:' and 'Age:' are silently stripped

String padded = """ Name:\s\s\s Age:\s\s\s\s """; // \s preserves the intended trailing spaces

The compiler automatically strips trailing whitespace from every line of a text block; use \s wherever a trailing or meaningful space must survive.

String json = """ { "key": "value" } """; // inconsistent indentation shifts the stripped margin unexpectedly

String json = """ { "key": "value" } """; // consistent indentation relative to the closing delimiter

The common-margin calculation is based on the least-indented non-blank line (and the closing delimiter). Inconsistent indentation across lines can produce a stripped margin that isn't what you expected — keep indentation levels deliberate and consistent.

What must immediately follow the opening """ of a text block?

A line terminator (a newline) — no other content, other than optional trailing whitespace, may appear on the same line as the opening triple-quote delimiter.

Is the value produced by a text block a different type from a regular string literal's value?

No — a text block is just alternate literal syntax; the resulting value is an ordinary java.lang.String, identical in type and behavior (interning, immutability, available methods) to one produced by a traditional double-quoted literal.

How does the compiler decide how much leading whitespace to strip from a text block?

It computes a common indentation margin based on the least-indented non-blank line among all the content lines, including the line holding the closing """ delimiter if it's on its own line — that shared amount of leading whitespace is stripped from every line.

What does \s do inside a text block, and why is it needed?

\s inserts an explicit space character that survives the compiler's automatic trailing-whitespace stripping. Without it, any trailing spaces you type at the end of a line inside a text block are silently removed.

What does a trailing backslash (\) at the end of a line do inside a text block?

It suppresses that line's newline in the resulting string, joining it to the next line — useful for wrapping a long logical line across multiple source lines without introducing a literal line break in the output.

Do you need to escape double quotes inside a text block?

Isolated double quotes (single or double " characters) need no escaping. Only a run of three consecutive unescaped quotes (""") is ambiguous with the closing delimiter and needs at least one \" to disambiguate.

In which Java version did text blocks become a standard, non-preview feature?

Java 15 (JEP 378), after being previewed in Java 13 (JEP 355) and Java 14 (JEP 368).

Write a text block containing a 3-line address (street, city, country) and print it, relying on automatic indentation stripping.

String address = """ 123 Main St Springfield USA """; System.out.print(address); // 123 Main St // Springfield // USA

Prints the three lines with no leading indentation in the output, even though the source is indented to match the surrounding code — the compiler strips the common margin based on the least-indented line.

What is the length of this text block's resulting String, and why?

3 — the string content is "a\nb" (a, newline, b): there is no trailing newline because the closing """ is placed immediately after 'b' on the same line rather than on its own line.

Write a text block SQL template with a placeholder, and use .formatted() to substitute a table name into it.

String template = """ SELECT * FROM %s WHERE active = true """; System.out.println(template.formatted("users")); // SELECT * // FROM users // WHERE active = true

Prints the SQL with 'users' substituted for %s — formatted() works on a text block exactly as it would on any other String, since a text block just produces a normal String value.

What does this print, and why?

true — the trailing spaces after 'x' are automatically stripped by the compiler (trailing whitespace stripping applies per line), so the resulting content is exactly "x\ny\n", matching the comparison string.

String s = """
    a
    b""";
System.out.println(s.length());
String s = """
    x   
    y
    """;
System.out.println(s.equals("x\ny\n"));