Contents

A text block opens with """ followed by a newline (the opening delimiter cannot be on the same line as content) and closes with """ on any line.

// Before text blocks — messy escape-heavy string String json = "{\n" + " \"name\": \"Alice\",\n" + " \"age\": 30\n" + "}"; // With text block — clean and readable String json = """ { "name": "Alice", "age": 30 } """; // Both produce the same string value System.out.println(json); // { // "name": "Alice", // "age": 30 // } // Text blocks are regular String objects — all String methods work System.out.println(json.getClass()); // class java.lang.String System.out.println(json.contains("Alice")); // true The opening """ must be followed immediately by a line break. Putting content on the same line as the opening delimiter is a compile error.

Java automatically strips incidental whitespace — leading spaces that exist only because of code indentation, not because they are part of the string content. The algorithm looks at the closing """ and strips the same number of leading spaces from every line.

class MyClass { String query = """ SELECT id, name FROM users WHERE active = true """; // The 12 spaces of indentation before SELECT are "incidental" // and are stripped. The result is: // "SELECT id, name\nFROM users\nWHERE active = true\n" } // Position of closing """ controls indentation stripping: // 1. Closing """ at column 0 — strips minimum indentation String a = """ line 1 line 2 """; // Result: " line 1\n line 2\n" (4-space indent preserved) // 2. Closing """ indented — strips more leading whitespace String b = """ line 1 line 2 """; // Result: "line 1\nline 2\n" (4 spaces stripped by closing """) // Trailing newline: if closing """ is on its own line, there IS a trailing \n // To suppress trailing newline, put closing """ right after last content: String noTrailing = """ hello"""; // "hello" — no trailing newline Text blocks always use \n (LF) as the line separator, regardless of the platform's line separator. This ensures consistent behavior across operating systems.

Java 15 introduced two new escape sequences specifically for use in text blocks:

// Line continuation — \ at end of line suppresses the newline String longUrl = """ https://example.com/api/v1/\ users?status=active&page=1\ """; // Result: "https://example.com/api/v1/users?status=active&page=1" // (no newlines, despite the multi-line source) // \s preserves trailing whitespace (useful in fixed-width formats) String padded = """ red \s green\s blue \s """; // Each line ends with exactly 2 spaces (the literal space + \s) // Standard escapes still work in text blocks String withQuotes = """ She said \"hello\" to everyone. He replied: it\'s fine. """;

Text blocks eliminate the escaping and concatenation noise that made multi-line string literals painful before Java 15. SQL queries, JSON payloads, HTML templates, and XML configurations become readable inline without backslash-n sequences or string concatenation on every line. Indentation is stripped based on the closing delimiter position — placing """ at the level of the content removes the code-level indent entirely. The underlying mechanisms are stripIndent() (available as a String method for runtime use) and translateEscapes(). Combine with formatted() to plug in dynamic values.

// SQL query — readable, no escape clutter String sql = """ SELECT u.id, u.username, o.total FROM users u JOIN orders o ON o.user_id = u.id WHERE u.active = true AND o.created_at > :since ORDER BY o.created_at DESC LIMIT :limit """; // JSON payload for HTTP request String requestBody = """ { "event": "user.signup", "data": { "username": "%s", "email": "%s", "plan": "free" } } """.formatted(username, email); // HTML email template String html = """ <!DOCTYPE html> <html> <body> <h1>Welcome, %s!</h1> <p>Your account is ready. <a href="%s">Click here</a> to get started.</p> </body> </html> """.formatted(name, loginUrl); // XML config String config = """ <?xml version="1.0" encoding="UTF-8"?> <configuration> <server port="8080" host="0.0.0.0"/> <database url="jdbc:postgresql://localhost/mydb"/> </configuration> """;

Several String methods are particularly useful with text blocks:

// formatted() — text block version of String.format() String greeting = """ Hello, %s! Your score is %d out of %d (%.1f%%). """.formatted("Alice", 95, 100, 95.0); // stripIndent() — programmatically strip incidental indent from a runtime string String runtime = " line1\n line2\n line3\n"; System.out.println(runtime.stripIndent()); // line1 // line2 // line3 // translateEscapes() — interpret escape sequences in a runtime string String withEscapes = "Hello\\nWorld"; // literal backslash-n System.out.println(withEscapes.translateEscapes()); // Hello // World // indent(n) — add or remove leading whitespace from each line String indented = "line1\nline2\n".indent(4); // " line1\n line2\n" String dedented = " line1\n line2\n".indent(-2); // " line1\n line2\n" Text blocks are a pure syntax feature — at runtime they are ordinary String objects. There is no performance difference from equivalent string concatenation at runtime.