ZetCode

Java Text Block

Last modified: July 16, 2026

This Java Text Block tutorial shows how to use text blocks (multi-line string literals) introduced in Java 13 as a preview feature and standardised in Java 15 (JEP 378). We cover text block syntax, indentation stripping, escape sequences, formatting with formatted, and practical examples.

Text Block

A text block is a multi-line string literal in Java that avoids the need for explicit line terminators, string concatenation, and escape sequences for special characters. It is delimited by three double-quote characters (""") at the opening and closing.

Text blocks significantly improve the readability of multi-line strings such as JSON, XML, HTML, SQL queries, or structured log messages. Instead of writing cumbersome concatenated or escaped strings, a text block preserves the natural formatting of the content.

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

The opening delimiter must be followed by a line terminator — the text begins on the next line. The closing delimiter determines the common indentation to be stripped.

Text block syntax

A text block starts with three double-quote characters followed by a line break. The content follows on subsequent lines and ends with another set of three double-quote characters.

Main.java
void main() {

    String text = """
        Hello there!
        This is a text block.
        It spans multiple lines.
        """;

    System.out.println(text);
}

The text block preserves the line breaks and the indentation of each line. The closing delimiter is placed on its own line to define the common left margin.

$ java Main.java
Hello there!
This is a text block.
It spans multiple lines.

The common leading whitespace shared by all lines (including the closing delimiter line) is automatically removed by the compiler. In the example above, eight spaces of indentation are stripped from each line.

Indentation stripping algorithm

Java applies a three-step algorithm to process text block content:

  1. Line terminators — all line terminators are normalized to \n.
  2. Incidental whitespace — the common leading whitespace is determined from all content lines and the closing delimiter line, then removed from each line.
  3. Trailing whitespace — trailing whitespace on each line is removed.

The amount of whitespace stripped is determined by finding the minimum indentation across all non-blank content lines and the closing delimiter line. This guarantees predictable formatting regardless of the code indentation level.

Main.java
void main() {

    String text = """
        {
            "name": "John Doe",
            "age": 42,
            "city": "New York"
        }
        """;

    System.out.println(text);
}

The minimum indentation (eight spaces, based on the closing delimiter line) is stripped from all lines. The JSON data retains its internal indentation.

$ java Main.java
{
    "name": "John Doe",
    "age": 42,
    "city": "New York"
}

Trailing whitespace

Java text blocks automatically remove trailing whitespace from each line. This prevents accidental whitespace at the end of lines and ensures consistent formatting. If trailing whitespace is semantically important, it can be preserved using the \s escape sequence or the \040 octal escape.

Main.java
void main() {

    String lines = """
        Line with trailing space\s
        Next line
        """;

    System.out.println(lines);
}

The \s escape forces a space character that is not trimmed. Without it, the trailing space before the line break would be removed.

$ java Main.java
Line with trailing space
Next line

Escape sequences in text blocks

Text blocks support all standard Java escape sequences plus two additional ones introduced specifically for text blocks: \s (space) and \<line-terminator> (line continuation).

Escape Meaning
\n Newline (U+000A)
\t Tab (U+0009)
\\ Backslash
\" Double quote (inside text block, " is also valid)
\s Space that is not trimmed (text block only)
\<newline> Line continuation — suppresses the line terminator (text block only)

The line continuation escape allows breaking a long line across multiple source lines without introducing an actual line break in the resulting string.

Main.java
void main() {

    String text = """
        Hello, \
        there! \
        How are you?
        """;

    System.out.println(text);
}

The backslash followed by a line break suppresses the line terminator, joining the text into a single line.

$ java Main.java
Hello, there! How are you?

Using the formatted method

Text blocks work seamlessly with the formatted instance method (equivalent to String.format) for string interpolation and formatting. This is the preferred way to inject dynamic values into a text block.

Main.java
void main() {

    String name = "John";
    int age = 42;
    String city = "New York";

    String msg = """
        Name: %s
        Age: %d
        City: %s
        """.formatted(name, age, city);

    System.out.println(msg);
}

The formatted method applies String.format style formatting to the text block. Each %s or %d placeholder is replaced with the corresponding argument.

$ java Main.java
Name: John
Age: 42
City: New York

Generating HTML

Text blocks are ideal for generating HTML templates without the need for string concatenation or escaping.

Main.java
void main() {

    String title = "ZetCode";
    String heading = "Java Text Blocks";
    String content = "Learn about multi-line strings.";

    String html = """
        <!DOCTYPE html>
        <html>
        <head>
            <title>%s</title>
        </head>
        <body>
            <h1>%s</h1>
            <p>%s</p>
        </body>
        </html>
        """.formatted(title, heading, content);

    System.out.println(html);
}

The HTML template uses %s placeholders for dynamic values. The formatted call replaces them at runtime.

$ java Main.java
<!DOCTYPE html>
<html>
<head>
    <title>ZetCode</title>
</head>
<body>
    <h1>Java Text Blocks</h1>
    <p>Learn about multi-line strings.</p>
</body>
</html>

Building SQL queries

Multi-line SQL queries benefit enormously from text blocks. The query structure is preserved and the indentation makes the SQL readable.

Main.java
void main() {

    String table = "employees";
    String condition = "salary > 50000";

    String query = """
        SELECT id, name, department, salary
        FROM %s
        WHERE %s
        ORDER BY salary DESC
        """.formatted(table, condition);

    System.out.println(query);
}

The SQL query is written in a natural indented format. The table name and WHERE condition are injected via formatted.

$ java Main.java
SELECT id, name, department, salary
FROM employees
WHERE salary > 50000
ORDER BY salary DESC

Embedding JSON

Text blocks make it easy to embed JSON data directly in source code without escaped quotes or concatenation.

Main.java
void main() {

    String json = """
        {
            "userId": 1,
            "userName": "johndoe",
            "email": "john@example.com",
            "roles": ["admin", "editor"]
        }
        """;

    System.out.println(json);

    // Formatting a JSON template
    int id = 2;
    String username = "janeb";
    String email = "jane@example.com";

    String json2 = """
        {
            "userId": %d,
            "userName": "%s",
            "email": "%s"
        }
        """.formatted(id, username, email);

    System.out.println(json2);
}

The first text block contains a static JSON structure. The second text block demonstrates dynamic JSON generation using formatted.

$ java Main.java
{
    "userId": 1,
    "userName": "johndoe",
    "email": "john@example.com",
    "roles": ["admin", "editor"]
}
{
    "userId": 2,
    "userName": "janeb",
    "email": "jane@example.com"
}

Indent method

The indent method adjusts the indentation of a text block by adding or removing leading whitespace from each line. A positive value adds spaces, a negative value removes spaces.

Main.java
void main() {

    String text = """
        first line
        second line
        third line
        """.indent(4);

    System.out.println(text);

    String text2 = """
            deep line
            another deep line
        """.indent(-4);

    System.out.println(text2);
}

indent(4) adds four spaces of indentation to each line. indent(-4) removes four spaces from each line (if available).

$ java Main.java
    first line
    second line
    third line

deep line
another deep line

Strip indent method

The stripIndent method removes the common leading whitespace from each line, similar to what the compiler does when parsing a text block. This is useful for re-indenting strings that were not originally defined as text blocks.

Main.java
void main() {

    String sql = """
            SELECT id, name
            FROM users
            WHERE active = true
            """.stripIndent();

    System.out.println(sql);
}

The stripIndent method removes the common indentation (12 spaces in this case) from all lines, producing a flush-left result.

$ java Main.java
SELECT id, name
FROM users
WHERE active = true

Translate escapes method

The translateEscapes method processes escape sequences in a string, converting recognised escape sequences (such as \n, \t) into their actual character equivalents. This is useful when escape sequences are received as literal text from an external source, such as a file or a network API, where the compiler has not processed them.

Main.java
void main() {

    // Simulating data read from an external file or API at runtime.
    // (In real life, this would be something like
    // Files.readString(Path.of("logs.txt")))
    // We use \\ here in the source code just to simulate receiving raw text
    // with literal backslashes.
    String rawLogData = "Timestamp: 10:05\\tStatus: ERROR\\n"
            + "Timestamp: 10:06\\tStatus: RECOVERED";

    System.out.println("--- Raw (unformatted) ---");
    System.out.println(rawLogData);

    System.out.println();
    System.out.println("--- With translateEscapes() ---");
    System.out.println(rawLogData.translateEscapes());
}

The string contains literal \t and \n characters — two characters each: a backslash followed by a letter. After calling translateEscapes, these are converted to actual tab and newline characters.

$ java Main.java
--- Raw (unformatted) ---
Timestamp: 10:05\tStatus: ERROR\nTimestamp: 10:06\tStatus: RECOVERED

--- With translateEscapes() ---
Timestamp: 10:05	Status: ERROR
Timestamp: 10:06	Status: RECOVERED
$ java Main.java
first line
second line
third line

Source

Java Text Blocks - Language Reference

In this article, we have worked with Java text blocks.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Java tutorials.