Text Blocks

Write multi-line JSON, SQL and HTML as readable text blocks, and control their indentation, trailing newline and escapes.

SyntaxString s = """ first line second line """; // closing on its own line: ends with \n

A text block, standard since Java 15, is a String literal that spans several lines. It is written between triple quotes and produces an ordinary String: same type, same methods, same pool. It exists so that SQL, JSON test fixtures and HTML snippets can be read as they will look, without \n and + on every line.

String sql = """
    SELECT id, email
    FROM users
    WHERE email = ?
    """;

The rules that matter

  • The opening """ must be followed by a line break. Content starts on the next line.
  • Incidental indentation is removed. The compiler finds the smallest indentation among the content lines and the closing delimiter line, and strips that much from every line. Your code can stay indented without the spaces ending up in the String.
  • The closing """ on its own line adds a final newline. Putting it at the end of the last content line leaves the newline out. Moving the closing delimiter to the left keeps extra indentation in the result.
  • Trailing spaces on each line are removed, and every line ending becomes \n, whatever the source file used. The same code produces the same String on Windows and Linux.

Escapes

Double quotes need no escaping inside a text block. Escape sequences are still processed, which has two useful additions: \s is a single space that survives trailing-space removal, and a backslash at the end of a line joins it to the next line without a newline. The catch is that a backslash meant for the output must be doubled. A JSON string containing \" has to be written as \\" in the text block, or the JSON you produce is invalid.

Text blocks with values

Pair a text block with formatted() to fill in values. That is fine for log messages, emails and tests. It is the wrong tool for two jobs that look similar:

  • SQL. Putting a value into the SQL text is SQL injection. Keep ? placeholders in the text block and bind values through PreparedStatement.
  • JSON. A value containing a quote or backslash breaks the document. Use a JSON library, or escape properly, for anything that came from a user.

Indent text blocks with spaces only. Tabs and spaces both count as one character of indentation, so a mix produces stripping that does not match what your editor shows.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Keep an expected JSON response in a test as a readable text block rather than an escaped one-line String.
  • Store a multi-line SQL query with ? placeholders as a constant in a repository class.
  • Write a plain-text email template and fill in the order number and name with formatted().

More examples

The closing delimiter controls indentation and the last newline

In the second block the closing delimiter sits four spaces left of the content, so four spaces of indentation are kept on each line, and because it is on its own line the String ends with a newline.

Example · java
void main() {
    String flush = """
        line one
        line two""";
    String indented = """
            line one
            line two
        """;

    IO.println(flush.equals("line one\nline two"));
    IO.println(indented.equals("    line one\n    line two\n"));
}
// Output:
// true
// true

\s and line continuation

\s keeps spaces that would otherwise be stripped as trailing whitespace, which matters for fixed-width formats. A backslash at the end of a line lets you lay out a long single-line String readably.

Example · java
void main() {
    String padded = """
        name\s\s
        id\s\s\s\s
        """;
    IO.print(padded.replace(' ', '.'));

    String oneLine = """
        SELECT id, name \
        FROM users \
        WHERE active = true""";
    IO.println(oneLine);
}
// Output:
// name..
// id....
// SELECT id, name FROM users WHERE active = true

Backslashes in JSON need doubling

The text block turns \" into a bare quote, so the first result is not valid JSON. Doubling the backslash puts a literal backslash into the String, which is what a JSON parser needs to see.

Example · java
void main() {
    String wrong = """
        {"message": "say \"hi\""}""";
    String right = """
        {"message": "say \\"hi\\""}""";

    IO.println(wrong);
    IO.println(right);
}
// Output:
// {"message": "say "hi""}
// {"message": "say \"hi\""}

Discussion

  • Be the first to comment on this lesson.