Text Blocks

Reviewed & published by Brayan K

A text block is a multi-line string literal — opened and closed with triple double-quotes — that lets you write JSON, SQL, and HTML naturally, without escaping every newline or gluing lines together with +.

Part of the free Java course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

Before You Start

You should know how ordinary Strings and escape sequences like \n work, and ideally have seen var. Text blocks need Java 15 or newer.

What You'll Learn

The Big Idea — Quote a Whole Page, Not Each Line

💡 Analogy: Writing a multi-line string the old way is like reading a poem aloud and saying "new line" after every single verse — exhausting and easy to get wrong ("a\n" + "b\n" + ...). A text block is like handing someone the printed page: the line breaks are already there. You write the text once, exactly as it should look, between two """ fences.

And because the compiler strips the indentation you used to line the block up with your code, the block looks neatly indented in your source but produces a clean, un-indented string.

1️⃣ Your First Text Block

Open with """ followed by a newline (nothing else may sit on that line), write your content, then close with """. Everything between is the string. The example below produces exactly the same String as the old concatenation-with-\n approach — proven with .equals.

public class Main {
    public static void main(String[] args) {
        // A text block: open with """ then a newline, close with """.
        String html = """
                <html>
                    <body>
                        <p>Hello, world!</p>
                    </body>
                </html>
                """;
        System.out.print(html);
        System.out.println("--- end ---");

        // The old way needed \n and + on every line:
        String oldWay = "<html>\n" +
                "    <body>\n" +
                "        <p>Hello, world!</p>\n" +
                "    </body>\n" +
                "</html>\n";
        System.out.println("Same text? " + html.equals(oldWay));
    }
}

2️⃣ Incidental Whitespace

The clever part: the compiler scans every content line and the closing """, finds the smallest shared leading indentation, and strips exactly that much from each line. That common, removable part is incidental whitespace; what remains is essential. This is how a block indented to match your code still yields an un-indented string.

In the second example below, moving the closing """ to the far left lowers the shared minimum, so four leading spaces survive on each line.

public class Main {
    public static void main(String[] args) {
        // Incidental whitespace: the compiler finds the least-indented line
        // (here the closing """) and strips that much from every line.
        String text = """
            line one
              line two indented
            line three
            """;
        System.out.println("[" + text + "]");

        // Moving the closing """ further left keeps more leading spaces.
        String shifted = """
            apple
            banana
        """;
        System.out.println("[" + shifted + "]");
    }
}

3️⃣ The \ and \s Escapes

Two escapes are unique to text blocks. A backslash at the end of a line removes that line's newline, so a long sentence can be wrapped across several source lines yet stay one line in the string. The \s escape is a single space that also blocks the compiler from trimming trailing spaces — useful when trailing spaces actually matter.

"""
abc \          <- line-join: no newline here
def"""          ->  "abc def"

"""
row\s"""        ->  "row " (the trailing space is kept)
public class Main {
    public static void main(String[] args) {
        // A trailing backslash joins a line to the next — no newline added.
        String oneLine = """
                The quick brown \
                fox jumps over \
                the lazy dog.""";
        System.out.println(oneLine);

        // \s is an "escaped space" — it preserves trailing spaces that
        // would otherwise be stripped, and is exactly one space.
        String padded = """
                key:value\s
                end""";
        System.out.println("[" + padded + "]");

        // You can still use \n and \" explicitly inside a text block.
        String quoted = """
                She said \"hi\".
                Next line.""";
        System.out.println(quoted);
    }
}

4️⃣ Filling Templates with .formatted()

Java has no ${name}-style interpolation. To drop values into a block, write %s / %d placeholders and call .formatted(args...) on it — a tidy instance shortcut for String.format. This makes text blocks ideal for JSON payloads and SQL queries built from variables.

public class Main {
    public static void main(String[] args) {
        String name = "Ada";
        int age = 36;

        // formatted() (or String.format) fills %s / %d placeholders.
        String json = """
                {
                    "name": "%s",
                    "age": %d,
                    "active": true
                }""".formatted(name, age);
        System.out.println(json);

        // A SQL query reads naturally as a text block.
        String sql = """
                SELECT id, name
                FROM users
                WHERE age >= %d
                ORDER BY name""".formatted(18);
        System.out.println();
        System.out.println(sql);
    }
}

🧠 Quick Recall

Predict the result before opening each answer.

String s = """hi
more""";

Answer: No. Content may not start on the opening line — the """ must be followed by a line terminator. Put hi on the next line.

String s = """
    ab""";

Answer: 2 — just ab. The four leading spaces are incidental (the closing """ sits at column 4 too) and there's no trailing newline because """ follows ab directly.

String a = """
done
""";
String b = """
done""";

Answer: a is "done\n" (closing """ on its own line adds a trailing newline); b is "done" with no newline. Delimiter placement controls the trailing newline.

🎯 Your Turn — A formatted report

Produce the exact multi-line report using a single text block and .formatted(...).

public class Main {
    public static void main(String[] args) {
        String city = "Paris";
        int temp = 21;

        // YOUR TURN: build this exact report with ONE text block and
        // .formatted(...) — no + concatenation.
        // Expected output:
        //   Weather report
        //   ---------------
        //   City: Paris
        //   Temp: 21 C

        // String report = """
        //         ...
        //         """.formatted(city, temp);
        // System.out.println(report);
    }
}

🧩 Mini-Challenge — Build an HTML list

Loop items into list rows, then wrap them in a <ul> using a text block.

public class Main {
    public static void main(String[] args) {
        String[] items = {"Milk", "Eggs", "Bread"};

        // MINI-CHALLENGE: build an HTML unordered list. Loop the items into
        // a StringBuilder of "  <li>...</li>\n" lines, then drop that into a
        // text block wrapped in <ul> ... </ul> using .formatted(...).
        //
        // Expected output:
        //   <ul>
        //     <li>Milk</li>
        //     <li>Eggs</li>
        //     <li>Bread</li>
        //   </ul>

        // StringBuilder lis = new StringBuilder();
        // for (String it : items) { ... }
        // String html = """
        //         <ul>
        //         %s</ul>""".formatted(lis.toString());
        // System.out.println(html);
    }
}

Common Errors

Pro Tips

📋 Quick Reference

ConceptSyntaxNote
Open delimiter""" + newlineNothing else on that line
Close delimiter"""Own line = trailing \n
No trailing newlinetext"""Close right after text
Indentation(automatic)Common leading WS stripped
Keep leading spacesmove """ leftLowers the shared minimum
Line joinend line with \Suppresses that newline
Keep trailing space\sOne space, not stripped
Single quote"No escaping needed
Insert valuesblock.formatted(args)%s, %d placeholders
Explicit newline\nStill works inside a block
Result typeStringNo new type involved

📚 Resources / Keep Learning

🎉 Lesson Complete!

You can now write multi-line strings cleanly with text blocks, you understand how incidental whitespace is stripped, you know the \ and \s escapes, and you can turn a block into a template with .formatted().

Practice quiz

How do you open a text block?

  • A single "
  • Three double-quotes followed by a line terminator
  • Backticks
  • Triple single-quotes

Answer: Three double-quotes followed by a line terminator. A text block opens with """ and a newline; content begins on the next line.

In which Java version did text blocks become a standard feature?

  • Java 8
  • Java 11
  • Java 15
  • Java 21

Answer: Java 15. Text blocks previewed in 13/14 and became standard in Java 15 (JEP 378).

What is 'incidental' whitespace?

  • Trailing spaces only
  • The common leading indentation the compiler strips
  • Tabs only
  • Whitespace inside strings

Answer: The common leading indentation the compiler strips. The compiler finds the minimum indentation across all lines (and the closing delimiter) and removes that much from every line.

What does a trailing backslash \ at the end of a line in a text block do?

  • Inserts a literal backslash
  • Suppresses the newline, joining the line to the next
  • Escapes a quote
  • Adds a space

Answer: Suppresses the newline, joining the line to the next. A line-ending \ removes the newline so two source lines become one logical line.

What does \s mean in a text block?

  • A tab
  • A newline
  • A single space that is not stripped
  • A null character

Answer: A single space that is not stripped. \s is an escaped space; it is exactly one space and prevents trailing-space stripping.

Where must the content of a text block start?

  • On the same line as the opening """
  • On the line after the opening """
  • Anywhere
  • At column 0

Answer: On the line after the opening """. Nothing except whitespace may follow the opening """ on its line; content starts on the next line.

Does the position of the closing """ affect indentation?

  • No
  • Yes — it participates in determining the common indentation to strip
  • Only in Java 21
  • Only with \s

Answer: Yes — it participates in determining the common indentation to strip. The closing delimiter's indentation is part of the whitespace calculation, so moving it left keeps more leading spaces.

How do you insert variable values into a text block?

  • Use ${var} interpolation
  • Text blocks cannot hold variables
  • Use .formatted(args) or String.format
  • Use + concatenation only

Answer: Use .formatted(args) or String.format. Java has no string interpolation; call .formatted(...) on the block (or String.format) to fill %s/%d placeholders.

Are you required to escape a single " inside a text block?

  • Yes, always
  • No — a lone double-quote is fine; only three in a row need care
  • Only at line start
  • Only in JSON

Answer: No — a lone double-quote is fine; only three in a row need care. Single and double quotes need no escaping inside a text block; you only manage sequences of three quotes.

What is the type of a text block expression?

  • char[]
  • StringBuilder
  • String
  • TextBlock

Answer: String. A text block is just a String literal written across multiple lines — its type is String.

Continue this course

Frequently asked questions

What exactly is a text block?

A text block is a multi-line String literal that opens with three double-quotes followed by a newline and closes with three double-quotes. Inside it you can write newlines, quotes, and indentation naturally, without or + concatenation on every line. Crucially, the result is just an ordinary String — there is no new TextBlock type. Text blocks previewed in Java 13 and 14 and became a permanent feature in Java 15.

How does indentation work — what is incidental whitespace?

The compiler looks at every content line and at the closing delimiter, finds the smallest amount of leading whitespace they share, and removes exactly that much from every line. That shared, removable indentation is called 'incidental' whitespace; whatever is left is 'essential' and stays in the string. This is why you can indent the whole block to line up with your code, yet the resulting string isn't indented. Moving the closing """ to the left keeps more leading spaces on every line.

What do the \ and \s escapes do?

A backslash at the very end of a content line suppresses the newline that would normally be added there, joining that line to the next — handy for wrapping one long logical line across several source lines. The \s escape inserts a single space and, because it counts as a non-whitespace marker, it also prevents the compiler from stripping trailing spaces on that line. Both escapes are unique to text blocks and solve the otherwise-awkward problems of long lines and meaningful trailing spaces.

Can I put variables inside a text block?

Not directly — Java has no string interpolation, so there is no ${name} syntax. The idiomatic approach is to write %s, %d, and other placeholders in the block and then call .formatted(args...) on it (which is shorthand for String.format). You can also concatenate with + after the block, but .formatted keeps multi-line templates clean and readable.

Do I need to escape quotes inside a text block?

A single double-quote needs no escaping at all, which is the whole point — you can write JSON, HTML, and SQL that contain quotes without a forest of backslashes. You only have to be careful with three or more double-quotes in a row, since """ could be read as the closing delimiter; in that rare case you escape one of them as \". Single quotes never need escaping.

Related lessons